C++的虚基类,抽象类,虚函数,纯虚函数,virtual_第1页
C++的虚基类,抽象类,虚函数,纯虚函数,virtual_第2页
C++的虚基类,抽象类,虚函数,纯虚函数,virtual_第3页
C++的虚基类,抽象类,虚函数,纯虚函数,virtual_第4页
C++的虚基类,抽象类,虚函数,纯虚函数,virtual_第5页
全文预览已结束

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、C+的虚基类,抽象类,虚函数,纯虚函数,virtual虚基类在说明其作用前先看一段代码classApublic:intiValue;classB:publicApublic:voidbPrintf()coutThisisclassBendl;classC:publicApublic:voidcPrintf()coutThisisclassCendl;classD:publicB,publicCpublic:voiddPrintf()coutThisisclassDendl;voidmain()Dd;coutd.iValueendl;/错误,不明确的访问coutd.A:iValueendl;/正

2、确coutd.B:iValueendl;/正确coutd.C:iValueendl;/正确从代码中可以看出类BC都继承了类A的iValue成员,因此类BC都有一个成员变量iValue,而类D又继承了BC,这样类D就有一个重名的成员iValue(一个是从类B中继承过来的,一个是从类C中继承过来的).在主函数中调用d.iValue因为类D有一个重名的成员iValue编译器不知道调用从谁继承过来的iValue所以就产生的二义性的问题正确的做法应该是加上作用域限定符d.B:iValue表示调用从B类继承过来的iValue。不过类D的实例中就有多个iValue的实例,就会占用内存空间。所以C+中就引用了

3、虚基类的概念,来解决这个问题。classApublic:intiValue;classB:virtualpublicApublic:voidbPrintf()coutThisisclassBendl;classC:virtualpublicApublic:voidcPrintf()coutThisisclassCendl;classD:publicB,publicCpublic:voiddPrintf()coutThisisclassDendl;voidmain()Dd;coutd.iValueendl;/正确在继承的类的前面加上virtual关键字表示被继承的类是一个虚基类,它的被继承成员在

4、派生类中只保留一个实例。例如iValue这个成员,从类D这个角度上来看,它是从类B与类C继承过来的,而类BC又是从类A继承过来的,但它们只保留一个副本。因此在主函数中调用d.iValue时就不会产生错误。虚函数还是先看代码classApublic:voidfunPrint()coutfunPrintofclassAendl;classB:publicApublic:voidfunPrint()coutfunPrintofclassBfunPrint();p=&b;p-funPrint();大家以为这段代码的输出结果是什么?有的人可能会马上回答funPrintofclassA与funPrinto

5、fclassB因为第一次输出是引用类A的实例啊,第二次输出是引用类B的实例啊。那么我告诉你这样想就错啦,答案是funPrintofclassA与funPrintofclassA至于为什么输出这样的结果不在本文讨论的范围之内;你就记住,不管引用的实例是哪个类的当你调用的时候系统会调用左值那个对象所属类的方法。比如说上面的代码类AB都有一个funPrint函数,因为p是一个A类的指针,所以不管你将p指针指向类A或是类B,最终调用的函数都是类A的funPrint函数。这就是静态联篇,编译器在编译的时候就已经确定好了。可是如果我想实现跟据实例的不同来动态决定调用哪个函数呢?这就须要用到虚函数(也就是动

6、态联篇)classApublic:virtualvoidfunPrint()coutfunPrintofclassAendl;classB:publicApublic:virtualvoidfunPrint()coutfunPrintofclassBfunPrint();p=&b;p-funPrint();在基类的成员函数前加virtual关键字表示这个函数是一个虚函数,所谓虚函数就是在编译的时候不确定要调用哪个函数,而是动态决定将要调用哪个函数,要实现虚函数必须派生类的函数名与基类相同,参数名参数类型等也要与基类相同。但派生类中的virtual关键字可以省略,也表示这是一个虚函数。下面来解决

7、一下代码,声明一个基类的指针(必须是基类,反之则不行)p,把p指向类A的实例a,调用funPrint函数,这时系统会判断p所指向的实例的类型,如果是A类的实例就调用A类的funPrint函数,如果是B类的实例就调用B类的funPrint函数。纯虚函数与其叫纯虚函数还不如叫抽象类,它只是声明一个函数但不实现它,让派生类去实现它,其实这也很好理解。classVehiclepublic:virtualvoidPrintTyre()=0;/纯虚函数是这样定义的;classCamion:publicVehiclepublic:virtualvoidPrintTyre()coutCamiontyrefou

8、rendl;classBike:publicVehiclepublic:virtualvoidPrintTyre()coutBiketyretwoendl;voidmain()Camionc;Bikeb;PrintTyre();PrintTyre();如上代码,定义了一个交通工具类(Vehicle),类中有一函数可打印出交通工具的轮胎个数,但交通工具很多轮胎个数自然也就不确定,所以就把它定义为纯虚函数,也就是光定义函数名不去实现它,类Camion继承了Vehicle并实现了里面的代码,打印出有4个轮胎。Bike类也是一样。有一点须要注意一下,纯虚函数不能实化化,但可以声明指针。总结虚基类一个类

9、可以在一个类族中既被用作虚基类,也被用作非虚基类。在派生类的对象中,同名的虚基类只产生一个虚基类子对象,而某个非虚基类产生各自的子对象。虚基类子对象是由最派生类的构造函数通过调用虚基类的构造函数进行初始化的。最派生类是指在继承结构中建立对象时所指定的类。派生类的构造函数的成员初始化列表中必须列出对虚基类构造函数的调用;如果未列出,则表示使用该虚基类的缺省构造函数。从虚基类直接或间接派生的派生类中的构造函数的成员初始化列表中都要列出对虚基类构造函数的调用。但只有用于建立对象的最派生类的构造函数调用虚基类的构造函数,而该派生类的所有基类中列出的对虚基类的构造函数的调用在执行中被忽略,从而保证对虚基

10、类子对象只初始化一次。在一个成员初始化列表中同时出现对虚基类和非虚基类构造函数的调用时,虚基类的构造函数先于非虚基类的构造函数执行。虚函数虚函数是非静态的、非内联的成员函数,而不能是友元函数,但虚函数可以在另一个类中被声明为友元函数。虚函数声明只能出现在类定义的函数原型声明中,而不能在成员函数的函数体实现的时候声明。一个虚函数无论被公有继承多少次,它仍然保持其虚函数的特性。若类中一个成员函数被说明为虚函数,则该成员函数在派生类中可能有不同的实现。当使用该成员函数操作指针或引用所标识的对象时,对该成员函数调用可采用动态联编。定义了虚函数后,程序中声明的指向基类的指针就可以指向其派生类。在执行过程中,该函数可以不断改变它所指向的对象,调用不同版本的成员函数,而且这些动作都是在运行时动态实现的。虚函数充分体

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论