菱形继承--菱形虚拟继承
菱形继承
菱形继承,其继承模型如下:
菱形继承存在问题,Teacher类和Student类都继承了Person类,所以Teacher类和Student类除了拥有自身的成员变量都还拥有继承于Person的成员变量。
而Assistant类继承了Teacher类和Student类,所以,Assistant类除了拥有自身的数据,还拥有Teacher类和Student类的,再加上Person的。那么问题来了,Assistant类中Person的部分是继承与那个父类的?还是都继承了?
看看下面代码:
//菱形虚继承
#include <iostream>
using namespace std;
class A
{
public:
void fun1()
{
cout << "A::fun1" << endl;
}
protected:
int _a = 10;
};
class B : public A
{
public:
void fun1()
{
cout << "B::fun1" << endl;
}
void fun2()
{
cout << "B::fun2" << endl;
}
protected:
int _b = 20;
};
class C : public A
{
public:
void fun1()
{
cout << "C::fun1" << endl;
}
void fun3()
{
cout << "C::fun3" << endl;
}
protected:
int _c = 30;
};
class D : public B, public C
{
public:
void fun1()
{
cout << "D::fun1" << endl;
}
void fun4()
{
cout << "D::fun4" << endl;
}
protected:
int _d = 40;
};
int main()
{
D d;
system("pause");
return 0;
}
通过监视窗口观察:
可以发现,D类除了拥有自身的数据,还拥有B类和C类的,再加上A的。而且A类是B类于C类中都有。那么就很难分清出,当调用D类中A类的那部分时,是从B类还是C类中拿到的。
可以发现菱形继承存在二义性与数据冗余问题。那么该如何解决呢?
通过虚继承的方式可以成功的解决问题:
#include <iostream>
using namespace std;
class A
{
public:
void fun1()
{
cout << "A::fun1" << endl;
}
protected:
int _a = 10;
};
class B : virtual public A
{
public:
void fun1()
{
cout << "B::fun1" << endl;
}
void fun2()
{
cout << "B::fun2" << endl;
}
protected:
int _b = 20;
};
class C : virtual public A
{
public:
void fun1()
{
cout << "C::fun1" << endl;
}
void fun3()
{
cout << "C::fun3" << endl;
}
protected:
int _c = 30;
};
class D : public B, public C
{
public:
void fun1()
{
cout << "D::fun1" << endl;
}
void fun4()
{
cout << "D::fun4" << endl;
}
protected:
int _d = 40;
};
int main()
{
D d;
system("pause");
return 0;
}
分析如下:
虚继承通过在菱形继承两个父类加上virtual达到虚继承。
虚继承--解决菱形继承的⼆义性和数据冗余的问题
-
虚继承解决了在菱形继承体系⾥⾯⼦类对象包含多份⽗类对象的数据冗余&浪 费空间的问题。
-
虚继承体系看起来好复杂,在实际应⽤我们通常不会定义如此复杂的继承体 系。⼀般不到万不得已都不要定义菱形结构的虚继承体系结构,因为使⽤虚继 承解决数据冗余问题也带来了性能上的损耗。
-