C++計(jì)算機(jī)語言教學(xué)課件c++-lect08C++VirtualFunctionsandPolymorphism_第1頁
C++計(jì)算機(jī)語言教學(xué)課件c++-lect08C++VirtualFunctionsandPolymorphism_第2頁
C++計(jì)算機(jī)語言教學(xué)課件c++-lect08C++VirtualFunctionsandPolymorphism_第3頁
C++計(jì)算機(jī)語言教學(xué)課件c++-lect08C++VirtualFunctionsandPolymorphism_第4頁
C++計(jì)算機(jī)語言教學(xué)課件c++-lect08C++VirtualFunctionsandPolymorphism_第5頁
已閱讀5頁,還剩53頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

Chapter7-C++VirtualFunctionsandPolymorphismOutline

7.1 Introduction 7.2 TypeFieldsand

switch

Statements 7.3 VirtualFunctions 7.4 AbstractBaseClassesandConcreteClasses

7.5 Polymorphism

7.6 NewClassesandDynamicBinding

7.7 VirtualDestructors

7.8 CaseStudy:InheritingInterfaceandImplementation7.9 Polymorphism,

virtual

FunctionsandDynamic Binding“UndertheHood”8.0 VirtualBaseClassandAbstractBaseClasses

ObjectivesInthischapter,youwilllearn:Tounderstandthenotionofpolymorphism.Tounderstandhowtodefineandusevirtualfunctionstoeffectpolymorphism.Tounderstandthedistinctionbetweenabstractclassesandconcreteclasses.Tolearnhowtodefinepurevirtualfunctionstocreateabstractclasses.Toappreciatehowpolymorphismmakessystemsextensibleandmaintainable.TounderstandhowC++implementsvirtualfunctionsanddynamicbinding“underthehood.”7.1IntroductionvirtualfunctionsandpolymorphismDesignandimplementsystemsthataremoreeasilyextensibleProgramswrittentogenericallyprocessobjectsofallexistingclassesinahierarchy(更通用的)在C++中,多態(tài)性(面向?qū)ο蟮木瑁┩ㄟ^虛函數(shù)實(shí)現(xiàn)。在基類的函數(shù)前加上virtual關(guān)鍵字,在派生類中重寫該函數(shù),運(yùn)行時(shí)將會(huì)根據(jù)對(duì)象的實(shí)際類型來調(diào)用相應(yīng)的函數(shù):如果對(duì)象類型是派生類,調(diào)用派生類的函數(shù),如果對(duì)象類型是基類,調(diào)用基類的函數(shù)。多態(tài)性概述賦值兼容原則:派生類的對(duì)象可以被當(dāng)成基類的對(duì)象來使用。派生類的對(duì)象可以賦值給基類的對(duì)象Baseb;Derived;b=d;派生類的對(duì)象可以初始化基類對(duì)象的引用Derived;Base&b=d;派生類對(duì)象的地址可以賦值給基類的指針Derivedd;Base*bPtr=&d;原因分析:1)派生類是基類的超集,并包含有基類的成員(繼承來的)。2)當(dāng)將派生類的對(duì)象賦值給基類的對(duì)象時(shí),系統(tǒng)將繼承來的成員賦值給基類的對(duì)象;3)當(dāng)將基類的對(duì)象賦值給派生類的對(duì)象將導(dǎo)致派生類的對(duì)象有未被復(fù)制成員(成員不夠)。內(nèi)存布局:父類部分內(nèi)存子類繼承部分this指針子類對(duì)象的內(nèi)存weneedtodefineabehaviorforoneobjectaccordingtoitstype7.2TypeFieldsand

switch

Statements

7.2TypeFieldsand

switch

Statements

switchstatement

Takeanactiononanobjectbasedonitstype根據(jù)類型來判斷哪個(gè)行為被調(diào)用AswitchstructurecoulddeterminewhichfunctiontocallbasedonwhichtypeinahierarchyProblemswithswitchProgrammermayforgettotestallpossiblecasesinaswitch.Trackingthisdowncanbetimeconsuminganderrorpronevirtualfunctionsandpolymorphicprogrammingcaneliminatetheneedforswitch7.3VirtualFunctionsvirtualfunctionsUsedinsteadofswitchstatementsDefinition:Keyword

virtual

beforefunctionprototypeinbaseclass

virtualvoiddraw()const;Abase-classpointerorreferencetoaderivedclassobjectwillcallthecorrectdrawfunction(在運(yùn)行時(shí),依據(jù)對(duì)象的類型(由對(duì)象的地址決定)確認(rèn)調(diào)用哪一個(gè)draw函數(shù))Ifaderivedclassdoesnotdefinea

virtualfunctionitisinheritedfromthebaseclass如果一個(gè)派生類沒有定義virtual,就直接繼承基類的函數(shù)(virtual就跟普通函數(shù)一樣)7.3VirtualFunctionsForexampleShapePtr->Draw();(指針型調(diào)用)CompilerimplementsdynamicbindingFunctiondeterminedduringexecutiontime動(dòng)態(tài)綁定ShapeObject.Draw();CompilerimplementsstaticbindingFunctiondeterminedduringcompile-time靜態(tài)綁定If引用,滿足動(dòng)態(tài)綁定PureVirtualFunctions純虛函數(shù)是一種特殊的虛函數(shù),格式如下,在參數(shù)列表后加“=0”:virtual<類型><函數(shù)名>(<參數(shù)表>)=0;含有(或繼承)一個(gè)或多個(gè)純虛函數(shù)的類是抽象基類。除了作為抽象基類的派生類的對(duì)象的組成部分,不能創(chuàng)建抽象類型的對(duì)象。引入的原因:在很多情況下,基類本身生成對(duì)象是不合情理的。例如,動(dòng)物作為一個(gè)基類可以派生出老虎、孔雀等子類,但動(dòng)物本身生成對(duì)象明顯不合常理。7.4AbstractandConcreteClassesAbstractclasses抽象類Solepurposeistoprovideabaseclassforotherclasses抽象類純虛函數(shù):純粹是規(guī)范一個(gè)接口NoobjectsofanabstractbaseclasscanbeinstantiatedToogenerictodefinerealobjects,i.e.TwoDimensionalShapeCanhavepointersandreferences可以有指針和引用Concreteclasses-classesthatcaninstantiateobjects具體類Providespecificstomakerealobjects,i.e.Square,Circle提供具體來創(chuàng)建一個(gè)真實(shí)的對(duì)象

7.4AbstractandConcreteClassesMakingabstractclassesDefineoneormorevirtualfunctionsas“pure”byinitializingthefunctiontozero純虛函數(shù)

virtualdoubleearnings()const=0;Purevirtualfunction當(dāng)存在一個(gè)或者多個(gè)純虛函數(shù)的類就是抽象類7.4AbstractandConcreteClassesMakingabstractclassesDefineoneormorevirtualfunctionsas“pure”byinitializingthefunctiontozero純虛函數(shù)

virtualdoubleearnings()const=0;Purevirtualfunction除非在派生類中完全實(shí)現(xiàn)基類中所有的的純虛函數(shù),否則,派生類也變成了抽象類,不能實(shí)例化對(duì)象。抽象類(AbstractClass)解決了什么問題。抽象類是一種特殊的類,它是為了抽象和設(shè)計(jì)的目的而建立的,它處于繼承層次結(jié)構(gòu)的較上層。抽象類是不能定義對(duì)象的,在實(shí)際中為了強(qiáng)調(diào)一個(gè)類是抽象類,可將該類的構(gòu)造函數(shù)說明為保護(hù)的訪問控制權(quán)限。抽象類的主要作用是將有關(guān)的組織在一個(gè)繼承層次結(jié)構(gòu)中,由它來為它們提供一個(gè)公共的根,相關(guān)的子類是從這個(gè)根派生出來的。抽象類刻畫了一組子類的操作接口的通用語義,這些語義也傳給子類。一般而言,抽象類只描述這組子類共同的操作接口,而完整的實(shí)現(xiàn)留給子類。

抽象類只能作為基類來使用,其純虛函數(shù)的實(shí)現(xiàn)由派生類給出。如果派生類沒有重新定義純虛函數(shù),而派生類只是繼承基類的純虛函數(shù),則這個(gè)派生類仍然還是一個(gè)抽象類。如果派生類中給出了基類純虛函數(shù)的實(shí)現(xiàn),則該派生類就不再是抽象類了,它是一個(gè)可以建立對(duì)象的具體類了。

7.4AbstractandConcreteClasses7.5PolymorphismPolymorphism:Abilityforobjectsofdifferentclassestoresponddifferentlytothesamefunctioncall

不同類型不同的響應(yīng)Base-classpointer(orreference)callsa

virtual

functionC++choosesthecorrectoverriddenfunctioninobjectSupposeprint

notavirtualfunction

Employeee,*ePtr=&e; HourlyWorkerh,*hPtr=&h; ePtr->print();//callbase-classprintfunction

hPtr->print();//callderived-classprintfunction

ePtr=&h;//allowableimplicitconversion

ePtr->print();//stillcallsbase-classprint7.5PolymorphismPolymorphism:Supposeprintisavirtualfunction Employeee,*ePtr=&e; HourlyWorkerh,*hPtr=&h; ePtr->print();//callbase-classprintfunction

hPtr->print();//callderived-classprintfunction

ePtr=&h;//allowableimplicitconversion

ePtr->print();//callderived-classprint7.6NewClassesandDynamicBindingDynamicbinding(latebinding)Object'stypenotneededwhencompilingvirtualfunctionsForexample,wecancompilethefollowingcode.voidprintEmp(Employee&e) {//類型參數(shù)可以是Employee或其派生類 Employee*ePtr=&e; ePtr->print();//若print函數(shù)為虛函數(shù),則根據(jù)參數(shù)e的實(shí) //際類型來調(diào)用對(duì)應(yīng)的print}Accommodate(允許)newclassesthathavebeenaddedaftercompilationImportantforISV’s(IndependentSoftwareVendors)whodonotwishtorevealsourcecodetotheircustomers可以把具體實(shí)現(xiàn)算法的派生類封裝到加密的代碼庫中。7.6NewClassesandDynamicBinding派生類與虛函數(shù)派生類一般會(huì)重定義所繼承的虛函數(shù)。派生類沒有重定義某個(gè)虛函數(shù),則使用基類中定義的版本。派生類中虛函數(shù)的聲明必須與基類中的定義方式完全匹配,但有一個(gè)例外:返回對(duì)基類型的引用(或指針)的虛函數(shù)。派生類中的虛函數(shù)可以返回派生類的引用(或指針)。(?)例如:Employee類可以定義返回Employee*的虛函數(shù),如果這樣,HourlyWorker類中的虛函數(shù)重寫可以定義為返回Employee*或HourlyWorker*。7.7VirtualDestructorsProblem:Ifbase-classpointertoaderivedobjectis

deleted,thebase-classdestructorwillactontheobject注意析構(gòu)函數(shù)的調(diào)用Solution:Defineavirtualbase-classdestructorNow,theappropriatedestructorwillbecalled7.7VirtualDestructors刪除指向動(dòng)態(tài)分配對(duì)象的指針時(shí),需要運(yùn)行析構(gòu)函數(shù)在釋放對(duì)象的內(nèi)存之前清除對(duì)象。處理繼承層次中的對(duì)象時(shí),指針的靜態(tài)類型可能與被刪除對(duì)象的動(dòng)態(tài)類型不同——?jiǎng)h除實(shí)際指向派生類對(duì)象的基類類型指針。(?)7.7VirtualDestructors如果刪除基類指針,則需要運(yùn)行基類析構(gòu)函數(shù)并清除基類的成員,如果對(duì)象實(shí)際是派生類型的,則沒有定義該行為。要保證運(yùn)行適當(dāng)?shù)奈鰳?gòu)函數(shù),基類中的析構(gòu)函數(shù)必須為虛函數(shù):classEmployee{public:

//nowork,butvirtualdestructorneeded

//ifbasepointerthatpointstoaderivedobjectisever //deleted

virtual~Employee(){}};7.7VirtualDestructors如果析構(gòu)函數(shù)為虛函數(shù),那么通過指針調(diào)用時(shí),運(yùn)行哪個(gè)析構(gòu)函數(shù)將因指針?biāo)笇?duì)象類型的不同而不同:Employee*itemE=new

Employee();//samestaticanddynamictypedelete

itemE;//ok:destructorforEmployeecalleditemE=new

HourlyWorker();//ok:staticanddynamictypesdifferdelete

itemE;

//ok:destructorforHourlyWorkercalled7.7VirtualDestructors最佳實(shí)踐:即使析構(gòu)函數(shù)沒有工作要做,繼承層次的根類也應(yīng)該定義一個(gè)虛析構(gòu)函數(shù)。構(gòu)造函數(shù)和賦值操作符不是虛函數(shù)構(gòu)造函數(shù)是在對(duì)象完全構(gòu)造之前運(yùn)行的,在構(gòu)造函數(shù)運(yùn)行的時(shí)候,對(duì)象的動(dòng)態(tài)類型還不完整。每個(gè)類有自己的賦值操作符,派生類中的賦值操作符有一個(gè)與類本身類型相同的形參。將賦值操作符設(shè)為虛函數(shù)可能會(huì)出錯(cuò),因?yàn)樘摵瘮?shù)必須在基類和派生類中具有同樣的形參。7.8CaseStudy:InheritingInterfaceandImplementationRe-examinethePoint,Circle,CylinderhierarchyUsetheabstractbaseclassShapetoheadthehierarchy先抽象出通用接口,設(shè)計(jì)一個(gè)基類ShapeDefinition(abstractbaseclass)---------------------1.PointDefinition(derivedclass)1//Fig.7.1:shape.h2//DefinitionofabstractbaseclassShape抽象類3#ifndef

SHAPE_H4#define

SHAPE_H56classShape{7public:8

virtualdoublearea()const{return

0.0;}9

virtualdoublevolume()const{return

0.0;}1011

//purevirtualfunctionsoverriddeninderivedclasses12

virtualvoidprintShapeName()const=0;13

virtualvoidprint()const=0;14};//endclassShape15#endif1.

PointDefinition(derivedclass)1.1FunctionDefinitions18//DefinitionofclassPoint19#ifndef

POINT1_H20#define

POINT1_H2122#include<iostream>2324usingstd::cout;26#include

"shape.h"2728classPoint:publicShape{29public:30Point(int=0,int=0);//defaultconstructor31

voidsetPoint(int,int);32

intgetX()const{returnx;}33

intgetY()const{returny;}34

virtualvoidprintShapeName()const{cout<<"Point:";}35

virtualvoidprint()const;36private:37

intx,y;

//xandycoordinatesofPoint38};//endclassPoint39#endif

1.

PointDefinition(derivedclass)1.1FunctionDefinitions41//Fig.7.1:point1.cpp42//MemberfunctiondefinitionsforclassPoint43#include

"point1.h"4445Point::Point(inta,intb){setPoint(a,b);}4647voidPoint::setPoint(inta,intb)48{49x=a;50y=b;}//endfunctionsetPoint

53voidPoint::print()const

54{cout<<'['<<x<<

","<<y<<']';}1.CircleDefinition(derivedclass)56//DefinitionofclassCircle57#ifndef

CIRCLE1_H58#define

CIRCLE1_H59#include

"point1.h"6061classCircle:publicPoint{62public:63

//defaultconstructor64Circle(doubler=0.0,intx=0,inty=0);6566

voidsetRadius(double);67

doublegetRadius()const;68

virtualdoublearea()const;69

virtualvoidprintShapeName()const{cout<<"Circle:";}70

virtualvoidprint()const;71private:72

doubleradius;//radiusofCircle73};//endclassCircle7475#endif1.1FunctionDefinitions77//MemberfunctiondefinitionsforclassCircle#include<iostream>usingstd::cout;82#include

"circle1.h"8384Circle::Circle(doubler,inta,intb)85:Point(a,b)

//callbase-classconstructor86{setRadius(r);}8788voidCircle::setRadius(doubler){radius=r>0?r:0;}8990doubleCircle::getRadius()const{returnradius;}9192doubleCircle::area()const

93{return

3.14159*radius*radius;}9495voidCircle::print()const96{97Point::print();98cout<<";Radius="<<radius;99}//endfunctionprint1.CylinderDefinition(derivedclass)101//DefinitionofclassCylinder102#ifndef

CYLINDR1_H103#define

CYLINDR1_H104#include

"circle1.h"105106classCylinder:publicCircle{107public:108//defaultconstructor109Cylinder(doubleh=0.0,doubler=0.0,110

intx=0,inty=0);111112

voidsetHeight(double);113

doublegetHeight();114

virtual

doublearea()const;115

virtualdoublevolume()const;116

virtualvoidprintShapeName()const{cout<<"Cylinder:";}117

virtualvoidprint()const;118private:119

doubleheight;//heightofCylinder120};//endclassCylinder122#endif1.1FunctionDefinitions

123//Fig.7.1:cylindr1.cpp124//MemberandfriendfunctiondefinitionsforclassCylinder125#include<iostream>126127usingstd::cout;128129#include

"cylindr1.h"130131Cylinder::Cylinder(doubleh,doubler,intx,inty)132:Circle(r,x,y)

//callbase-classconstructor133{setHeight(h);}1341351.1FunctionDefinitions134135voidCylinder::setHeight(doubleh)136{height=h>0?h:0;}137138doubleCylinder::getHeight(){returnheight;}139140doubleCylinder::area()const141{142

//surfaceareaofCylinder143

return

2*Circle::area()+144

2*3.14159*getRadius()*height;145}//endfunctionarea146Driver1.Loadheaders1.1Functionprototypes

147doubleCylinder::volume()const

148{returnCircle::area()*height;}149150voidCylinder::print()const151{152Circle::print();153cout<<";Height="<<height;

}//endfunctionprint

Driver1.Loadheaders1.1Functionprototypes155//Fig.7.1:fig20_01.cpp156//Driverforshape,point,circle,cylinderhierarchy157#include<iostream>158159usingstd::cout;160usingstd::endl;161162#include<iomanip>163164usingstd::ios;165usingstd::setiosflags;166usingstd::setprecision;167168#include

"shape.h"169#include

"point1.h"170#include

"circle1.h"171#include

"cylindr1.h"1721.2Initializeobjects2.Functioncalls

173voidvirtualViaPointer(constShape*);174voidvirtualViaReference(constShape&);175176intmain()177{178cout<<setiosflags(ios::fixed|ios::showpoint)179<<setprecision(2);180181Pointpoint(7,11);//createaPoint182Circlecircle(3.5,22,8);//createaCircle183

Cylindercylinder(10,3.3,10,10);//createaCylinder184185point.printShapeName();//staticbinding186point.print();

//staticbinding187cout<<'\n';1881981.2Initializeobjects2.Functioncalls188189circle.printShapeName();//staticbinding190circle.print();//staticbinding191cout<<'\n';192193cylinder.printShapeName();//staticbinding194cylinder.print();//staticbinding195cout<<

"\n\n";196197Shape*arrayOfShapes[3];//arrayofbase-classpointers1982.Functioncalls

199

//aimarrayOfShapes[0]atderived-classPointobject200arrayOfShapes[0]=&point;201202

//aimarrayOfShapes[1]atderived-classCircleobject203arrayOfShapes[1]=&circle;204205

//aimarrayOfShapes[2]atderived-classCylinderobject206arrayOfShapes[2]=&cylinder;207208

//LoopthrougharrayOfShapesandcallvirtualViaPointer209

//toprinttheshapename,attributes,area,andvolume210

//ofeachobjectusingdynamicbinding.211cout<<"Virtualfunctioncallsmadeoff"212<<"base-classpointers\n“;2.Functioncalls213214

for(inti=0;i<3;i++)215virtualViaPointer(arrayOfShapes[i]);216217

//LoopthrougharrayOfShapesandcallvirtualViaReference218

//toprinttheshapename,attributes,area,andvolume219

//ofeachobjectusingdynamicbinding.220cout<<"Virtualfunctioncallsmadeoff"221<<"base-classreferences\n";2223.FunctionDefinitions223

for(intj=0;j<3;j++)224virtualViaReference(*arrayOfShapes[j]);225226

return

0;227}//endfunctionmain228229//Makevirtualfunctioncallsoffabase-classpointer230//usingdynamicbinding.

231voidvirtualViaPointer(constShape*baseClassPtr)

232{

233baseClassPtr->printShapeName();

234baseClassPtr->print();

235cout<<

"\nArea="<<baseClassPtr->area()236<<"\nVolume="<<baseClassPtr->volume()<<"\n\n";237}//endfunctionvirtualViaPointer

3.FunctionDefinitions238239//Makevirtualfunctioncallsoffabase-classreference240//usingdynamicbinding.241voidvirtualViaReference(constShape&baseClassRef)242{243baseClassRef.printShapeName();244baseClassRef.print();245cout<<"\nArea="<<baseClassRef.area()246<<"\nVolume="<<baseClassRef.volume()<<"\n\n";247}

//endfunctionvirtualViaReferenceProgramOutputPoint:[7,11]Circle:[22,8];Radius=3.50Cylinder:[10,10];Radius=3.30;Height=10.00

Virtualfunctioncallsmadeoffbase-classpointersPoint:[7,11]Area=0.00Volume=0.00

Circle:[22,8];Radius=3.50Area=38.48Volume=0.00

Cylinder:[10,10];Radius=3.30;Height=10.00Area=275.77Volume=342.12

Virtualfunctioncallsmadeoffbase-classreferencesPoint:[7,11]Area=0.00Volume=0.00

Circle:[22,8];Radius=3.50Area=38.48Volume=0.00

Cylinder:[10,10];Radius=3.30;Height=10.00Area=275.77Volume=342.12Override,OverloadandHideOverride(重寫),是指派生類重寫基類的虛函數(shù)。重寫的虛函數(shù)必須有一致的參數(shù)表和返回值(注意特殊情況)。Overload(重載),是指編寫一個(gè)與已有函數(shù)同名但是參數(shù)表不同的函數(shù)。例如一個(gè)函數(shù)即可以接受整型數(shù)作為參數(shù),也可以接受浮點(diǎn)數(shù)作為參數(shù)。

Hide(隱藏或遮蔽),是指派生類中的函數(shù)屏蔽了基類中相同名字的函數(shù)。遮蔽可以理解為特殊的覆蓋和特殊的重載,分為兩種情況:派生類的函數(shù)與基類的函數(shù)同名,但參數(shù)表不同。

(特殊的重載)派生類的函數(shù)與基類的函數(shù)同名且參數(shù)表相同,但沒有加上virtual關(guān)鍵字。

(特殊的重寫)7.9Polymorphism,

virtualFunctionsandDynamicBinding“UndertheHood”在面向?qū)ο蟮木幊讨?,首先?huì)針對(duì)數(shù)據(jù)進(jìn)行抽象(確定基類)和繼承(確定派生類),構(gòu)成類層次。這個(gè)類層次的使用者在使用它們的時(shí)候,如果仍然在需要基類的時(shí)候?qū)戓槍?duì)基類的代碼,在需要派生類的時(shí)候?qū)戓槍?duì)派生類的代碼,就等于類層次完全暴露在使用者面前。如果這個(gè)類層次有任何的改變(增加了新類),都需要使用者“知道”(針對(duì)新類寫代碼)。這樣就增加了類層次與其使用者之間的耦合。7.9Polymorphism,

virtualFunctionsandDynamicBinding“UndertheHood”多態(tài)可以使程序員脫離這種窘境。再回頭看看下面的例子感受一下。假設(shè)我們實(shí)現(xiàn)一個(gè)有100種動(dòng)物的動(dòng)物園系統(tǒng)。由于其中不同種類的動(dòng)物有著不同的eat和sleep行為,所以不能把eat和sleep提取出到基類Animal中。如何讓所有種類的動(dòng)物eat和sleep呢?不用多態(tài)不用多態(tài),函數(shù)調(diào)用只能在編譯時(shí)綁定。這就我們需要自己指定每一種動(dòng)物,然后調(diào)用它自己的eat和sleep函數(shù)??梢阅繙y(cè),這會(huì)嚴(yán)重降低效率,同時(shí)使工作變得異常枯燥。動(dòng)物們的吃飯的代碼如下:

dog.eat(); donkey.eat(); chichen.eat();parrot.eat();horse.eat();monkey.eat();donkey.eat();mule.eat();pig.eat();cow.eat();deer.eat();ox.eat();goat.eat();lion.eat();tiger.eat();fox.eat();wolf.eat();bear.eat();…

動(dòng)物們的睡覺的代碼如下:

dog.sleep(); donkey.sleep(); chichen.sleep();parrot.sleep();horse.sleep();monkey.sleep();donkey.sleep();mule.sleep();pig.sleep();cow.sleep();deer.sleep();ox.sleep();goat.sleep();lion.sleep();tiger.sleep();fox.sleep();wolf.sleep();bear.sleep();…

創(chuàng)建對(duì)象的代碼如下:

Dogdog; Donkeydonkey; Chichenchichen;Parrotparrot;Horsehorse;Monkeymonkey;Donkeydonkey;Mulemule;Pigpig;Cowcow;Deerdeer;Oxox;Goatgoat;Lionlion;Tigertiger;Foxfox;Wolfwolf;Bearbear;…

使用多態(tài)創(chuàng)建對(duì)象的代碼如下:

Animal*ptr[100];ptr[0]=newDog; ptr[1]=newDonkey;ptr[2]=newChichen;ptr[3]=newParrot;…ptr[98]=newHorse;ptr[99]=newMule;動(dòng)物們的吃飯的代碼如下:

for(inti=0;i<100;i++){ptr[i]->eat();}動(dòng)物們睡覺的代碼如下:for(inti=0;i<100;i++){ptr[i]->sleep();}這完全歸功于多態(tài)--編譯器針對(duì)虛函數(shù)產(chǎn)生了可以在運(yùn)行時(shí)刻確定被調(diào)用函數(shù)的代碼。7.9Polymorphism,

virtualFunctionsandDynamicBinding“UndertheHood”WhentousePolymorphism在你設(shè)計(jì)一個(gè)基類的時(shí)候,如果發(fā)現(xiàn)一個(gè)函數(shù)需要在派生類里有不同的表現(xiàn),那么它就應(yīng)該是虛的。從設(shè)計(jì)的角度講,出現(xiàn)在基類中的虛函數(shù)是接口,出現(xiàn)在派生類中的虛函數(shù)是接口的具體實(shí)現(xiàn)。通過這樣的方法,就可以將對(duì)象的行為抽象化。7.9Polymorphism,

virtualFunctionsandDynamicBinding“UndertheHood”Compile-timeBinding(編譯期綁定,alsocalledStaticBinding)和Run-timeBinding(運(yùn)行期綁定,alsocalledDynamicBinding)。Binding(綁定):決定執(zhí)行哪一段代碼。

voidsayHi(){ cout<<“Hello!”<<endl;}

intmain(){ sayHi();

return0;}將sayHi的調(diào)用綁定到sayHi的實(shí)現(xiàn)處:編譯器將所有對(duì)sayHi的調(diào)用視為執(zhí)行代碼:

cout<<“Hello!”<<endl;C++編譯期綁定和運(yùn)行期綁定一個(gè)函數(shù)的名稱對(duì)應(yīng)了該函數(shù)在內(nèi)存中的起始地址,常稱作該函數(shù)的入口地址。編譯期綁定:執(zhí)行哪一段代碼由編譯器在編譯階段決定;即函數(shù)的入口地址在編譯時(shí)確定。運(yùn)行期綁定:執(zhí)行哪一段代碼是在運(yùn)行階段決定;即函數(shù)的入口地址在運(yùn)行時(shí)確定。1 classBase{2public:3 voidf(){cout<<“Base::f()”<<endl;}4};5

classDerive:publicBase{6

public:7

voidf(){cout<<“Derive::f()”<<endl;}9 };10

int

main(){

Base*ptr=NULL;

ptr=newDerive;

ptr->f(); deleteptr; return0;

}

Base::f()Output編譯期綁定:在編譯時(shí),根據(jù)ptr的數(shù)據(jù)類型Base*進(jìn)行綁定,即綁定到Base::f()。編譯期綁定和運(yùn)行期綁定的區(qū)別1 classBase{2public:3 virtualvoidf(){cout<<“Base::f()”<<endl;}4};5

classDerive:publicBase{6

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論