C++ 菱形继承和虚拟菱形继承

菱形继承和虚拟菱形继承

  • 菱形继承
    • 1. 概念
    • 2. 产生的问题
  • 虚拟菱形继承
    • 1.1 使用
    • 1.2 原理

菱形继承

1. 概念

菱形继承是多继承的一个特殊情况,多继承是指一个子类类继承了两个或以上的直接父类,而菱形继承问题的产生是因为该子类的父类,继承了同一个父类,注意是父类而不是直接父类。下面这张图就是直接父类,因为形状像一个菱形就称为菱形继承,但如果不是直接父类,这个形状就不是菱形了,但还是菱形继承。
C++ 菱形继承和虚拟菱形继承_第1张图片

2. 产生的问题

那菱形继承会导致什么问题呢?由图可以很容易看出,这样会导致D对象有两份A,会产生数据冗余和二义性的问题。
C++ 菱形继承和虚拟菱形继承_第2张图片
我们通过代码看看A是不是有两份

class A
{
protected:
	int _a;
};

class B :public A
{
protected:
	int _b;
};

class C : public A
{
protected:
	int _c;
};

class D : public B, public C
{
protected:
	int _d;
};

int main()
{
	D d;
	cout << sizeof(d);
	return 0;
}

在这里插入图片描述
再看看是不是有二义性问题

class A
{
public:
	int _a;
};

class B :public A
{
protected:
	int _b;
};

class C : public A
{
protected:
	int _c;
};

class D : public B, public C
{
protected:
	int _d;
};

int main()
{
	D d;
	cout << d._a;
	return 0;
}

在这里插入图片描述
下面的虚拟菱形继承可以解决这些问题。

虚拟菱形继承

1.1 使用

使用非常的简单,我们只需要在继承的时候加上virtual关键字就行了,但要注意的是virtual只需要加在会产生两份的继承位置,比如B、C都继承A,这就需要加上virtual关键字,而D继承B、C就不需要用关键字。

class A
{
public:
	int _a = 1;
};

class B :virtual public A
{
protected:
	int _b = 2;
};

class C :virtual public A
{
protected:
	int _c = 3;
};

class D : public B, public C
{
protected:
	int _d = 4;
};

int main()
{
	D d;
	cout << d._a;
	return 0;
}

在这里插入图片描述

1.2 原理

我们可以通过成员对象模型来研究原理。
我们通过内存窗口先来看一下没有虚拟继承的菱形继承对象模型
C++ 菱形继承和虚拟菱形继承_第3张图片
很明显的可以看到A有两份,造成了数据冗余和二义性,我们在来看一下虚拟继承以后的对象模型。
C++ 菱形继承和虚拟菱形继承_第4张图片
可以看到A只有一份,成功的解决了问题,但又产生了一个新问题,A不在B和C里,那B和C如何找到A呢?看上面的模型,细心的同学会发现B和C多了一个东西,那个东西就是解决这个问题的关键,叫做虚基表指针,指向的是一个虚基表,表里面存放的是偏移量,通过这个偏移量找到A

你可能感兴趣的:(c++,开发语言)