您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 经营企划 > 团队学生技术交流讲座(XXXX)_ 第2课_理解C++虚拟多态机制
理解C++虚拟与多态机制机器视觉团队技术交流讲座第02讲•主讲教师杨程目录•多态性•虚函数与动态绑定•纯虚函数与抽象类•实例讲解•习题和课后阅读资料多态性多态性的定义•何谓多态性?–多态性是指给同样的接口发送同样的消息会导致不同的行为。–多态意味着一个对象有着多重特征,可以在特定的情况下,表现不同的状态,从而对应着不同的属性和方法。•多态性是面向对象程序设计的重要特征之一。–若程序设计语言不支持多态性,不能称为面向对象的语言。C++多态性•C++有哪些多态性机制?–函数重载–运算符重载–虚函数•函数重载和运算符重载是编译时体现出来的多态性,虚函数则体现了运行时的多态性。虚函数与动态绑定示例:乐器类继承体系类定义Instrument——乐器Wind——管乐器Woodwind——木管乐器Brass——铜管乐器Percussion——打击乐器Stringed——弦乐器接口说明play——演奏adjust——调整乐器what——显示乐器信息类型的向上转换(Upcasting)•将派生类地址(指针或引用)沿着继承树向上的方向赋给基类指针(赋值兼容原则)•Upcasting将对象按传址(byaddress)而非传值(byvalue)方式进行操作,而多态性需通过Upcasting来体现。我们想做什么?•提供给用户一个通用的不变的系统使用接口——函数tune(),无论类进行了怎样的变动,这个接口都能正常可靠地工作(总能按照我们的期望选出正确的乐器演奏)我们想做什么?•我们的要求是合理的,这种要求系统具备动态识别能力的需求,在实际运行的很多软件系统当中都是一项基本要求,这正是要求系统具备多态性。voidtune(Instrument&i){i.play();}intmain(){Windflute;tune(flute);//Upcasting}先看一个例子…•#includeiostream•usingnamespacestd;•enumnote{middleC,Csharp,Eflat};.•classInstrument{•public:•voidplay(note)const{•coutInstrument::playendl;•}•};•//WindobjectsareInstruments•//becausetheyhavethesameinterface:•classWind:publicInstrument{•public:•//Redefineinterfacefunction:•voidplay(note)const{•coutWind::playendl;•}•};•voidtune(Instrument&i){•//...•i.play(middleC);•}•intmain(){•Windflute;•tune(flute);//Upcasting•return0;•}•我们定义了Wind对象flute,通过接口tune操作play函数,显然我们希望flute对象能正确地调用Wind类的play函数运行的结果…•#includeiostream•usingnamespacestd;•enumnote{middleC,Csharp,Eflat};.•classInstrument{•public:•voidplay(note)const{•coutInstrument::playendl;•}•};•//WindobjectsareInstruments•//becausetheyhavethesameinterface:•classWind:publicInstrument{•public:•//Redefineinterfacefunction:•voidplay(note)const{•coutWind::playendl;•}•};•voidtune(Instrument&i){•//...•i.play(middleC);•}•intmain(){•Windflute;•tune(flute);//Upcasting•return0;•}•程序却调用了基类Instrument的play函数,显然这不是我们希望的结果!•问题出在哪儿了呢?改动一下例子…•#includeiostream•usingnamespacestd;•enumnote{middleC,Csharp,Eflat};.•classInstrument{•public:•virtualvoidplay(note)const{•coutInstrument::playendl;•}•};•//WindobjectsareInstruments•//becausetheyhavethesameinterface:•classWind:publicInstrument{•public:•//Redefineinterfacefunction:•voidplay(note)const{•coutWind::playendl;•}•};•voidtune(Instrument&i){•//...•i.play(middleC);•}•intmain(){•Windflute;•tune(flute);//Upcasting•return0;•}•将基类函数play函数定义成为虚函数(virtualfunction)初见虚函数•虚函数(virtualfunction)的定义virtual返回类型函数名(参数表);classShape{private:…public:virtualvoidDraw(){cout“Drawashape”endl;}};派生类中的虚函数•虚函数是类成员函数(classmemberfunction);•在派生类(derivedclass)中对虚函数的实现重新定义称之为覆盖(override)•虚函数的“身份”在继承之间能被持续传递下去再次运行,结果…•#includeiostream•usingnamespacestd;•enumnote{middleC,Csharp,Eflat};.•classInstrument{•public:•virtualvoidplay(note)const{•coutInstrument::playendl;•}•};•//WindobjectsareInstruments•//becausetheyhavethesameinterface:•classWind:publicInstrument{•public:•//Redefineinterfacefunction:•voidplay(note)const{•coutWind::playendl;•}•};•voidtune(Instrument&i){•//...•i.play(middleC);•}•intmain(){•Windflute;•tune(flute);//Upcasting•return0;•}•这次结果是我们希望的结果!•我们引入了虚函数机制,导致了这样的结果。“神奇的”执行方式?•以基类指针运行虚函数,程序就能执行我们所期望的正确的派生类的函数体,虚函数为什么会有这样“神奇的”运行机制呢?•通过继承而相关的不同类,他们的对象能够对同一个函数作出不同的响应.这样“神奇的”多态性是怎样实现的呢?静态绑定与动态绑定•绑定(binding)–程序自身彼此关联的过程,确定程序中的操作调用与执行该操作的代码间的关系。•静态绑定(earlybinding)–绑定过程出现在编译阶段,用对象名或者类名来限定要调用的函数。•动态绑定(dynamic/laterbinding)–绑定过程工作在程序运行时执行,在程序运行时才确定将要调用的函数。“神奇的”执行方式——动态绑定•C++的虚函数在运行时正是通过动态绑定实现多态机制的。•动态绑定是如何实现的呢?•动态绑定是通过编译器运用虚函数表VTBL和虚表指针VPTR而实现,在运行时通过动态查询实现对正确函数体的绑定。VTBL–编译器会为声明了虚函数的类建立一个虚函数表。–VTBL实际上是一个函数指针数组,每个虚函数占用这个数组的一个入口(slot)。–一个类只有一个VTBL,不管它有多少个实例。–派生类有自己的VTBL,但是派生类的VTBL与基类的VTBL有相同的函数排列顺序,同名的虚函数被放在两个数组的相同位置上。VPTR•在创建类实例的时候,编译器还会在每个实例的内存布局中增加一个VPTR指针,该指针指向本类的VTBL。最后,是动态联编•在调用此类的构造函数时,在类的构造函数中,编译器会隐含执行VPTR与VTBL的关联代码,将VPTR指向对应的VTBL。这就将类与此类的VTBL联系了起来。•在调用类的构造函数时,指向基类的指针此时已经变成指向具体的类的this指针,依靠此this指针,进一步得到正确的VPTR,即可得到正确的VTBL,从而实现了多态性。在此时才能真正与函数体进行连接,这就是动态联编。一个更大的例子…•#includeiostream•usingnamespacestd;•enumnote{middleC,Csharp,Cflat};//Etc.•classInstrument•{•public:•virtualvoidplay(note)const•{coutInstrument::playendl;}•virtualchar*what()const•{returnInstrument;}•virtualvoidadjust(int){}•};•classWind:publicInstrument•{•public:•voidplay(note)const•{coutWind::playendl;}•char*what()const{returnWind;}•voidadjust(int){}•};•classPercussion:publicInstrument•{•public:•voidplay(note)const•{coutPercussion::playendl;}•char*what()const{returnPercussion;}•voidadjust(int){}•};•classStringed:publicInstrument•{•public:•voidplay(note)const•{coutStringed::playendl;}•char*what()const•{returnStringed;}•voidadjust(int){}•};一个更大的例子…•classBrass:publicWind•{•public:•voidplay(note)const•{coutBrass::playendl;}•char*what()const•{returnBrass;}•};•classWoodwind:publicWind•{•public:•voidplay(note)const•{coutWoodwind::playendl;}•char*what()const•{returnWoodwind;}•};•voidtune(Instrument&i)•{•i.play(middleC);•}•voidf(Instrument&i)•{•i.adjust(1);•}•//Upcastingduringarrayinitialization:•Instrument*A[]=•{•newWind,•newPercussion,•newStringed,•newBrass,•};一个更大的例子…•intmain()•{Windflute;Percussiondrum;Stringedviolin;Brassflugelhorn;Woodwindrecorder;tune(flute);tune(drum
本文标题:团队学生技术交流讲座(XXXX)_ 第2课_理解C++虚拟多态机制
链接地址:https://www.777doc.com/doc-730986 .html