什么是多重继承:如图
什么是多继承:如图
继承中的特殊结构
菱形继承结构带来的问题,D会有两个A中的数据成员
class A{public:int a;};class B:public A{public:int b;};class C:public A{public:int c;};class D:public B,public C{public:int d;};D中会有两个a一个是从B继承的,一个是从C继承的
出现这样的问题,有两种解决方案
一是我们可以这样访问,避免二义性
D obj;
cout<<obj.B::a<<endl;
cout<<obj.C::a<<endl;
二是可以使用虚继承
虚继承之后
D obj;
cout<<obj.a<<endl;
不会出现二义性
虚基类通过虚基类表解决了二义性问题
CDerived d;
vbptr指的是虚基类表指针(virtual base table pointer),该指针指向了一个虚基类表(virtual table),虚表中记录了虚基类与本类的偏移地址;通过偏移地址,这样就找到了虚基类成员,而虚继承也不用像普通多继承那样维持着公共基类(虚基类)的两份同样的拷贝,只需要一份拷贝,节省了存储空间。
包含虚基类的派生类的构造函数 从虚基类A直接派生的派生类B的构造函数的成员初始化列表中,必须列出对虚基类A构造函数的调用,调用时提供的参数用来初始化从虚基类A继承的数据,如果没有列出则表示调用虚基类A的缺省或无参数或者带缺省参数值的构造函数。从虚基类A派生出派生类B,然后又用B派生出派生类C(从虚基类间接派生)的构造函数的成员初始化列表中,既必须列出对基类B构造函数的调用,也必须列出对虚基类A构造函数的调用。此时基类B构造函数在执行时将不再调用其虚基类A的构造函数而只是用提供给B构造函数的参数对派生类对象从B类继承的数据初始化,用于调用虚基类A的构造函数的参数被丢弃,以保证派生类继承的虚基类的数据只能被初始化列表中列出的对A类构造函数的调用提供的参数来初始化。如果没有列出对虚基类A的构造函数的调用,则表示使用虚基类A的缺省或无参数或带缺省参数值的构造函数。如果构造函数成员初始化列表中,同时出现对虚基类和非虚基类构造函数的调用时,虚基类的构造函数先于非虚基类的构造函数执行。如果构造函数成员初始化列表中,有多个对虚基类构造函数的调用时,则按照派生类定义时,虚基类出现次序从左至右地执行。非虚基类的构造函数若有多个也是如此。