大家好:
衷心希望各位点赞。
您的问题请留在评论区,我会及时回答。
菱形继承概念
两个派生类继承同一个基类
又有一个类同时继承这两个派生类
这种继承被称为菱形继承,或者钻石继承。
基类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继承了两个变量a
system("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;
}
运行截图:
总结
菱形继承导致的问题:子类继承两份相同的数据,导致内存资源浪费且毫无意义。
利用虚继承,可以解决菱形继承导致的问题。