190 likes | 333 Views
Data Structures - CSCI 102. CS102. C++ Polymorphism. Prof Tejada. 1. Data Structures - CSCI 102 Polymorphism What is polymorphism ? The ability of an object of one type to appear and be used like an object of a different type Remember our Shape and Triangle classes?
E N D
DataStructures-CSCI102 CS102 C++Polymorphism Prof Tejada 1
DataStructures-CSCI102 Polymorphism Whatispolymorphism? Theabilityofanobjectofonetypetoappearandbe usedlikeanobjectofadifferenttype RememberourShapeandTriangleclasses? Basedoninheritance,TriangeIs-AShapeso... WecanactuallypassTrianglesaroundasShapes! Trianglet(5,5,15,20); Shapetval=t; Shape&tref=t; Shape*tptr=&t; Shape*tptr2=newTriangle(1,2,55,62); Youcanwriteveryadvancedcodewithpolymorphism Writealgorithms&frameworksthatmanipulatebaseclass Canevenwritecodeforsubclassesthathasn’t beenrealizedordesigned! 3
DataStructures-CSCI102 Polymorphism Sowhatdoesthiscodedo? Trianglet(5,5,15,20); t.print(); Shapetval=t; tval.print(); Shape&tref=t; tref.print(); Shape*tptr=&t; tptr->print(); ItshouldcalltheTriangleobject’soverloadedprintmethod, right?Doesit? 4
DataStructures-CSCI102 Early/Static/Compile-TimeBinding EventhoughwecanpassaroundaTriangleasaShape,it doesn’thelpifwecan’tmakeitcallTriangle’soverloaded methods Whydoesthishappen? Whenyourcodeiscompiled,thecompilerdirectly associatesafunctioncallwithamemorylocationto makefunctioncallsafastlookup Whenyoucompilersees"s.print()",itimmediately associatesitwiththeShapeclass Isn’ttheresomewaytotellthecompilertowaituntil run-timetofigureoutwhatversionofthe"print()"function itshouldcall? 5
DataStructures-CSCI102 VirtualFunctions TellstheC++towaituntilthecoderunstofigureoutwhat versionofamethoditshouldactuallycall ThekeywordvirtualtellsC++tofindthe"most-derived" versionofamethod(a.k.a.theonefarthestdownthe inheritancetreethat’sstillrelevant) Howisitused? Justaddthekeywordvirtualtothebeginningofany functionprototypeinyourclass Technically,youonlyhavetoaddvirtualtothe superclassmethod,butit’sgoodstyleifyouaddittoall ofthefunctionsthatareaffectedbyit Whynotjustdeclareeveryfunctionvirtual? It’smoreexpensivethannormallookup(time& space) 6
DataStructures-CSCI102 VirtualFunctions Beforewehadthis: classShape{ ... voidprint()const; }; Nowwehavethisinstead: classShape{ ... virtualvoidprint()const; }; 7
DataStructures-CSCI102 Late/Dynamic/Run-TimeBinding Howdoesthevirtualkeywordactuallywork? IttellsC++thatit’snotpossibletoknowwhatversionof thatparticularfunctiontocalluntilrun-time Thecompilerconstructsavirtualtableforeveryclass thathasavirtualfunction Eachoftheseclassesstoresahiddenpointertoitsown virtualtable Thevirtualtableprovidesarun-timelookupforeach classtoknowwhatversionoffunctionstocallusing functionpointers 8
DataStructures-CSCI102 Other"Virtual"Details Ifyou’reusinginheritance,youshouldALWAYSmakeyour baseclass’Destructorvirtual Ifyoudon’tC++willonlycallthesuperclassdestructor andwillskipyoursubclassdestructor Dynamicbindingonlyworksforreferencesandpointers!!! Trianglet(5,5,15,20); t.print(); Shapetval=t; tval.print();//callsShape’sprint()!!! Shape&tref=t; tref.print();//callsTriangle’sprint() Shape*tptr=&t; tptr->print();//callsTriangle’sprint() 9
DataStructures-CSCI102 Polymorphism Whyispolymorphismuseful? Allowsyoutoreusealotofcodethatworksforsimilar objects Allowsyoutoaddnewclassestoyourinheritance hierarchy,butallyourexistingmethodswillstillwork justfine! Whatifweaddanewsubclassof"Shape"? Allowsyoutoconstructverysophisticatedcodethatis simple,butpowerful 10
DataStructures-CSCI102 PureVirtualFunctions Whatifthere’safunctionthatthesuperclasscan’tdefine, butweneedthesubclassestodefine? classShape{ virtualdoublegetArea()const; }; TheproblemhereisthatShapehasnodetailsabouthowto calculateanarea.Ourfunctionwouldenduplooking somethinglikethis(notveryuseful): doubleShape::getArea()const {return0;} 11
DataStructures-CSCI102 PureVirtualFunctions ThegetArea()functionisnotmeaningfulforShape,butitis meaningfulforallsubclassesofShape NeedtomakegetArea()asapurevirtualfunction ShapedoesnotneedtoimplementgetArea() Allsubclassesofshapeshouldbeforcedtoimplementa definitionofgetArea() classShape{ virtualdoublegetArea()const=0; }; 12
DataStructures-CSCI102 AbstractBaseClasses Whataretheconsequencesofmakingafunctioninaclass apurevirtualfunction? IfShapecontainsapurevirtualfunction,itcannolonger beinstantiated! WhatwouldhappenifyoumadeaShapeobjectand triedtocallgetArea()? Shapebecomesanabstractbaseclass AnysubclassofShapethatdoesn’timplementareal versionofgetArea()alsobecomesanabstractbaseclass! Ifyouwanttouseyourderivedclasses,youMUST overridethegetArea()method 13
DataStructures-CSCI102 PolymorphicPrintFunction Hereisanexampleofafunctionthatisimplementedusing polymorphismtomaintainflexibility: voidprintArea(constShape&s) { cout<<"Area="<<s.getArea()<<endl; } WhatifwedecidetoaddanothersubclasslikeRectangleto ourexistinginheritancehierarchy? Youwon’tneedtochangeprintArea()! 14
DataStructures-CSCI102 InterfaceClasses Usingtheideasofpurevirtualfunctionsandabstractbase classesyoucouldcreateaclassthathasno implementationatall! Aninterfaceclassisaclassthatcontainsonlypurevirtual functions Veryusefulforwhenyouwanttotellsubclasseswhat functionstheymustprovide,butyoudon’twantto influencetheirimplementation It’sabetter/saferwaytodomultipleinheritance(Java andC#actuallysplitinterfaceout) Actually,itisTHErightwaytodomultipleinheritance InterfaceclassesusuallyprefixtheirnamewithI e.g."Shape"wouldbecome"IShape" 15
DataStructures-CSCI102 polymorph_point.h #ifndefPOLYMORPH_POINT_H_ #definePOLYMORPH_POINT_H_ #include<iostream> classPoint { private: intx; inty; public: Point(intnewx,intnewy):x(newx),y(newy){} virtual~Point(){}//Avirtualdestructor intgetX()const{return intgetY()const{return voidsetX(intnewx){x= voidsetY(intnewy){y= x;} y;} newx;} newy;} friendstd::ostream&operator<<(std::ostream&out, constPoint&b); }; std::ostream&operator<<(std::ostream&out,constPoint&b) { out<<"("<<b.x<<","<<b.y<<")"; returnout; } #endif/*POLYMORPH_POINT_H_*/ 17
DataStructures-CSCI102 polymorph_shape.h #ifndefPOLYMORPH_SHAPE_H_ #definePOLYMORPH_SHAPE_H_ #include"polymorph_point.h" classShape { protected: Pointcenter; public: Shape(intx,inty) :center(x,y) {} //Avirtualdestructor virtual~Shape(){} PointgetCenter()const{returncenter;} voidsetCenter(Pointp){center=p;} //Avirtualprintfunction virtualvoidprint()const { std::cout<<"Shapelocatedat"<<center<<std::endl; } //Apurevirtualareacalculationfunction virtualdoublegetArea()const=0; }; #endif/*POLYMORPH_SHAPE_H_*/ 18
DataStructures-CSCI102 polymorph_triangle.h #ifndefPOLYMORPH_TRIANGLE_H_ #definePOLYMORPH_TRIANGLE_H_ #include"polymorph_point.h" #include"polymorph_shape.h" classTriangle:publicShape { private: intbase; intheight; public: Triangle(intb,inth,intx,inty):Shape(x,y) {base=b;height=h;} intgetBase()const{ intgetHeight()const voidsetBase(intb){ voidsetHeight(inth) returnbase;} {returnheight;} base=b;} {height=h;} virtualvoidprint()const {std::cout<<"Trianglelocatedat"<<center <<std::endl;} virtualdoublegetArea()const {return(.5*base*height);} }; #endif/*POLYMORPH_TRIANGLE_H_*/ 19
DataStructures-CSCI102 polymorph_rectangle.h #ifndefPOLYMORPH_RECTANGLE_H_ #definePOLYMORPH_RECTANGLE_H_ #include"polymorph_point.h" #include"polymorph_shape.h" classRectangle:publicShape { private: intwidth; intheight; public: Rectangle(intw,inth,intx,inty):Shape(x,y) {width=w;height=h;} intgetWidth()const{returnwidth;} intgetHeight()const{returnheight;} voidsetBase(intw){width=w;} voidsetHeight(inth){height=h;} virtualvoidprint()const {std::cout<<"Rectanglelocatedat"<<center <<std::endl;} virtualdoublegetArea()const {return(width*height);} }; #endif/*POLYMORPH_RECTANGLE_H_*/ 20
DataStructures-CSCI102 polymorph_main.cpp #include<iostream> #include<string> #include #include #include #include "polymorph_point.h" "polymorph_shape.h" "polymorph_triangle.h" "polymorph_rectangle.h" usingnamespacestd; voidprintArea(constShape&s) { cout<<"Areaofshapeis"<<s.getArea()<<endl; } intmain() { Triangle*t=newTriangle(10,10,10,10); printArea(*t); deletet; Rectangle*r=newRectangle(10,15,20,25); printArea(*r); deleter; } 22