C++学习-多继承和虚基类

转载 2015年11月18日 10:29:21

本文主要是讨论类的多继承,多继承的方式可使派生类具有多个基类的特性。以下是一个继承关系,C从A和B基类中派生出来,在派生类C中,包含了基类A与基类B的成员,还有C类自己的成员。

在上述关系图中,可以看到,类继承的结构很清晰,但在很多时候,有可能有以下继承关系:


在这幅类的继承关系图中可以看到,B1和B2分别继承于A,再由B1和B2派生出C,这关系看起来很简单,但在内部,有点麻烦?
产生二义性。
A派生出B1和B2,所以B1和B2中分别包含A的成员,再由B1和B2派生出C,此时C包含了B1和B2类的成员,所以C中总共有2个A成员。这时候麻烦了,如何要对C类中B1父类中的A类成员修改,或者是对C类中的B2父类中的A类成员修改呢?这有点绕口,C++提供了一种方法是通过作用域来指定,可以参考前一篇博文《C++学习-继承中的作用域(10)

这里给一个简单的例子:



执行结果:
B1::mA = 30
B2::mA = 50
mB1 = 20
mB2 = 40
mC = 10

从这个例子可以看到,使用作用域运算符"::"来消除二义性,这样就能巧妙地避免那个棘手的问题。不过在类C中,包含了2个A的部分,有点浪费空间。当然C++是非常伟大的,还有另一种更好的办法,就是使用虚基类,也可以称为虚继承。
虚基类的作用:使用虚基类能够在多重派生的过程中,使公有的基类在派生类中只有一个拷贝,这样就能解决上述二义性的错误。如果使用虚基类,那么以上类C当中也就只有1个A的部分。在虚基类的使用过程中,还有一个非常重要的特性,看例子便可发现
看例子:



执行结果:
B1::mA = 0
B2::mA = 0
mA = 0
mB1 = 20
mB2 = 40
mC = 10

B1::mA = 163
B2::mA = 163
mA = 163
mB1 = 20
mB2 = 40
mC = 10

对比一下这两个例子,差别很小,将作用域的调用方式给去掉了。在这个例子当中,使用了virtual方式继承了基类A,所以在B1和B2中,对类A只有一个拷贝,若使用virtual方式继承,不管派生多少派生类,类A永远只有一个拷贝。对mA进行修改,从B1或B2调用mA,都是调用同一个副本,从结果可以看出这一结论。
重要:
虚基类的构造函数的调用方法与一般基类的构造函数的调用方法是不同的
。在这个例子中,编译器没有调用B1或者B2的构造函数来调用基类A的构造函数,因为在虚继承过程中,基类A只有一个拷贝,所以编译器无法确定应该由类B1或者类B2的构造函数来调用基类A的构造函数,所以此时调用的是基类A的默认构造函数,所以刚开始mA的结果为0,是基类A的默认构造函数设置的默认值。

C++规定,由虚基类经过一次或者多次派生出来的派生类,在其每一个派生类的构造函数的成员初始化列表中必须给出对虚基类的构造函数的调用,如果未列出,则调用虚基类的默认构造函数。
在本例当中,在执行B1和B2的构造函数时都不调用虚基类A的构造函数,而是在类C中的构造函数直接调用虚基类A的默认构造函数。(因为编译器无法确定)
再看一个与上面几乎是一样的例子,只有一个区别,就是在类C的初始化列表中显示的调用虚基类A的构造函数,如下:



执行结果:
B1::mA = 20
B2::mA = 20
mA = 20
mB1 = 20
mB2 = 40
mC = 10

B1::mA = 163
B2::mA = 163
mA = 163
mB1 = 20
mB2 = 40
mC = 10

唯一的区别就是这行代码:
C(int x, int a, int b, int c, int d) : A(a), B1(a, b), B2(c, d), mC(x) {}
在这里显示地调用虚基类A的构造函数,并传入初始值,所以第一次打印mA的值不是0,而是20。



C++虚基类的作用、用法和意义

教科书上面对C++虚基类的描述玄而又玄,名曰“共享继承”,名曰“各派生类的对象共享基类的的一个拷贝”,其实说白了就是解决多重多级继承造成的二义性问题。例如有基类B,从B派生出C和D,然后类F又同时继承...

c++中的 虚函数 纯虚函数 虚基类

原文出自http://blog.csdn.net/dardgen/article/details/18790977 虚函数 ,纯虚函数, 虚基类,它们都和virtual有关,这三个带有虚字的...

C++虚基类的作用

虚基类的作用     当一个基类被声明为虚基类后,即使它成为了多继承链路上的公共基类,最后的派生类中也只有它的一个备份。例如:class CBase { };class CDerive1:virtua...

c++继承之虚基类

虚基类的概念:        若在多继承派生类中继承的基类再拥有一个公共基类,则这个公共基类会在多继承派生类的对象中产生多个公共基类子对象,如果要使这个公共基类再多继承派生类中只产生一个基类子对象,则...

C++虚基类的实现机制

在《深度探索C++对象模型》里,有一个问题,也是去公司面试的时候那些技术人员常问的问题:在C++中,obj是一个类的对象,p是指向obj的指针,该类里面有个数据成员mem,请问obj.mem和p->m...

C++ 虚基类的初始化

如果一个派生类有多个基类,而这些直接基类又有一个共同的基类,则在最终的派生类中会保留该间接数据成员的多份同名成员。 使用虚基类可使最终的派生类只保留共同基类的一份同名成员。 一般情况下,派生类的构造函...

C++虚基类的作用

参考自:http://blog.csdn.net/caomiao2006/article/details/4463664 虚基类的作用       当一个基类被声明为虚基类后,即使它成为了多...

c++多继承与虚基类

转载自:http://blog.csdn.net/insistgogo/article/details/6653301 多继承的定义:派生类的基类大于一个 语法: [...

C++多继承与虚基类

》多继承中的二义性问题         在派生类中对基类成员的访问应该是唯一的。但是,在多继承情况下,可能造成对基类中某个成员的访问出现了不唯一的情况,这时就称对基类成员的访问产生了二义性。   ...

Qt Model/View(MVD)模型分析

最近在看Qt的Model/View Framework,在网上搜了搜,好像中文的除了几篇翻译没有什么有价值的文章。E文的除了Qt的官方介绍,其它文章也很少。看到一个老外在blog中写道Model/Vi...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++学习-多继承和虚基类
举报原因:
原因补充:

(最多只允许输入30个字)