虚继承节省空间,解决二义性问题。

虚拟继承是多重继承中特有的概念。虚拟基类是为解决多重继承而出现的。如下图所示。

类D继承自类B1、B2,而类B1、B2都继承自类A,因此出现如右图所示的局面(非虚基类)。

为了节省内存空间,可以将B1、B2对A的继承定义为虚拟继承,而A就成了虚拟基类。最后形成如左图所示的情况。

实现的代码如下:

虚基类和非虚基类的区别

class A;

class B1:public virtual A;

class B2:public virtual A;

class D:public B1,public B2;

虚继承后,在B、C中都分别包含了一个指向A的虚基类指针列表vbptr(virtual base table pointer)(虚基表指针),其中记录的是从B、C的vbtable的首地址(vbptr)到A的元素之间的偏移量。此时,不会生成各子类的函数f标识,除非子类重写了该函数,从而达到“共享”的目的

#include<iostream>
using namespace std;
class A
{
public:
	int a;
};
class B :public A
{
public:
	int b;
};
class C :public A
{
public:
	int c;
};
class D :public B, public C
{
public:
	int d;
};
int main()
{
	D d;
	*(int*)(&d) = 0;//d.B::a = 0;或者这样,指明类域,这样写更好
	*(int*)((int)&d+sizeof(B)) = 0;//d.B::a = 0;
	d.b = 2;
	d.c = 3;
	d.d = 4;
	return 0;
}

wKioL1cfKDyxx2nkAABI8GKvmQM623.png


wKiom1cfJ2_wI6ApAABhK4cHHSs168.png

//虚继承
class A
{
public:
	int a;
};
class B :virtual public A
{
public:
	int b;
};
class C :virtual public A
{
public:
	int c;
};
class D :public B, public C
{
public:
	int d;
};
int main()
{
	D d;
//	*(int*)(&d) = 0;
	//*(int*)((int)&d+sizeof(B)) = 0;
	d.B::a = 0;
	d.B::a = 1;
	d.b = 2;
	d.c = 3;
	d.d = 4;
}

wKioL1cfLA6D6qo0AACcigYkecQ583.png

虚表存储也是一样

wKioL1cgXKPCUyg5AABp8gpt8j4713.png