虚继承---满足菱形关系才有虚继承
引入虚继承:
-
A类中有一个a属性,A继承产生子类B类有一个属性a,A类再继承产生子类C类也有一个属性a,B、C类继承产生D类 → 普通的继承方式让D类中有两个属性a,最终产生的子类有两个拷贝本,a由谁决定?
解决方案:
-
让相同的属性只保留一份(两个a只有一个有效)--->(A继承产生B、C类必须要用虚继承,用virtual修饰的继承[类似近亲结婚导致的基因问题])--->这份a必须让A的构造函数初始化(在D类中调用A类(祖先类)的构造函数)
-
子类中相同的属性a,必须要由它祖父类的构造函数初始化(由A类决定)
-
菱形继承:必须调用祖父类的构造函数
-
注意:构造函数的写法
虚继承---virtual修饰的继承方式
class B :virtual public A
{
};
class C :virtual public A
{
};
用 virtual 修饰的方式,导致a属性只有1个备份,所有a都是一样的 → 在A|B|C|D类中的a的值是一样的,无论用什么访问方式a属性都是一样的,只要是祖父类的属性,在父类中就没有用了
//虚继承 --->菱形继承
class A
{
public:
A(int a) :a(a) {}
protected:
int a;
};
class B :virtual public A //必须要用虚继承
{
public:
B(int a, int b) :A(a), b(b) {} //调用A的构造函数
protected:
int b;
};
class C :virtual public A //必须要用虚继承
{
public:
C(int a, int c) :A(a),c(c) {}
void printC()
{
cout << a << endl;
}
protected:
int c;
};
class D :public C, public B //B和C继承产生D类:采用菱形继承
{
public:
//多继承中只用调用父类构造函数即可依旧报错:类A不存在默认构造函数
D() :B(1, 2), C(3, 4) ,A(999) //,A(999)这里必须调用祖父类的构造函数
{
}
void print()
{
//用virtual继承,a由祖父类的构造函数决定,和父类的构造函数无关
cout << a << endl;
cout << B::a << endl; //只有一个a,没有3个a,所有的a都是同一个值
cout << C::a << endl;
printC(); //间接访问也是一样的
}
protected:
};
int main()
{
D d;
d.print();
}
/*输出*/
999
999
999
999 B类、C类中的a属性没有继承过来 B:1 C:3