大家好:
衷心希望各位点赞。
您的问题请留在评论区,我会及时回答。
菱形继承概念
两个派生类继承同一个基类
又有一个类同时继承这两个派生类
这种继承被称为菱形继承,或者钻石继承。
基类A同时派生出类B和类C,派生类D又同时继承类B和类D,这就是菱形继承。
菱形继承的问题
类B和类C都继承了基类A的数据,这样的话,当类D访问数据时就有可能发生二义性,
类D把基类A的数据继承了两份,但是,这份数据其实我们只需要一份就可以了。
#include <iostream>
#include <Windows.h>using namespace std;class A
{
public:int a;A(){a = 0;}
};class B : public A
{// 类B继承一份数据a
};class C : public A
{// 类C继承一份数据a
};class D : public B, public C
{// 类D继承两份数据a,分别来自类B和类C
};int main(void)
{D d;cout << d.a << endl; // 报错:访问d.a不明确,因为D继承了两个变量asystem("pause");return 0;
}
解决方法:
利用虚继承,解决菱形继承所导致继承两份基类数据的问题。这样的话,派生类D就只会继承一份基类A的数据。
在基类的继承方式前,加上关键字 virtual ,此时,基类称为虚基类。
#include <iostream>
#include <Windows.h>using namespace std;class A
{
public:int a;A(){a = 10;}
};class B : virtual public A // 虚基类A
{/**类B继承虚基类指针vbptr,指向虚基类表vbtable(存放偏移量)。*vbptr加上vbtable的偏移量就能指向基类A的数据,这样,就只用保存一份基类A的数据。*/
};class C : virtual public A
{/**类C继承虚基类指针vbptr,指向虚基类表vbtable(存放偏移量)。*vbptr加上vbtable的偏移量就能指向基类A的数据,这样,就只用保存一份基类A的数据。*/
};class D : public B, public C
{// 类D只继承了一份数据a
};int main(void)
{D d;cout << d.a << endl; // 打印10,只有一份数据a system("pause");return 0;
}
运行截图:
总结
菱形继承导致的问题:子类继承两份相同的数据,导致内存资源浪费且毫无意义。
利用虚继承,可以解决菱形继承导致的问题。