虚基类
还是上面的二义性问题2,Child类通过两条路径,产生了爷爷类Base的多个实例,例如通过Child的对象,可以访问到Base类的两个不同的数据成员b,一个是通过Base1类继承来的,一个是通过Base2类继承来的。虚基类的作用就是让Child只有一个Base类的实例。
使用虚基类的继承称为虚拟继承。虚基类是相对于子类而言的,所以虚基类本身定义不需要修改,只是子类在继承的时候加关键字virtual
#include <iostream>
using namespace std;
class Base
{
public:
void func(){cout<<"Base func"<<endl;}
int b;
};
class Base1:virtual public Base
{
public:
void func(){cout<<"Base1 func"<<endl;}
};
class Base2:virtual public Base
{
public:
void func(){cout<<"Base2 func"<<endl;}
};
class Child:public Base1,public Base2
{
public:
int func(){return Base1::b+Base2::b};
};
void main()
{
Child c;
c.Base1::b=8;
c.Base2::b=16;
cout<<"Base1 b="<<c.Base1::b<<endl;
cout<<"Base2 b="<<c.Base2::b<<endl;
c.Base1::func();
c.Base2::func();
c.Base::func();
}
注意第9和第14行,在继承方式Public前面的关键字,说明了这是虚基类继承。注意输出结果为:
Base1 b=16
Base2 b=16
Base1 func
Base2 func
Base func
前两行输出,b的值都是16,说明了Child对象c中只有一个Base类的实例。还有最后一行输出,通过c.Base::func(),调用到了Base类的函数,也说明Child对象c中只有一个Base类的实例。因为如果是两个Base实例的话,编译器就不知道是Base1中继承来的,还是Base2中继承来的了。
虚基类的构造函数
注意构造函数的调用顺序:
1.先基类,后子类
2.有多个基类,先虚基类,后非虚基类
3.有多个虚基类,按照定义时的顺序依次构造
4.虚基类的构造函数只执行依次。(这就是Child对象c中只有一个Base类的实例)