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

菱形继承

1. 概念

菱形继承是多继承的一个特殊情况,多继承是指一个子类类继承了两个或以上的直接父类,而菱形继承问题的产生是因为该子类的父类,继承了同一个父类,注意是父类而不是直接父类。下面这张图就是直接父类,因为形状像一个菱形就称为菱形继承,但如果不是直接父类,这个形状就不是菱形了,但还是菱形继承。
在这里插入图片描述

2. 产生的问题

那菱形继承会导致什么问题呢?由图可以很容易看出,这样会导致D对象有两份A,会产生数据冗余和二义性的问题。
在这里插入图片描述
我们通过代码看看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 原理

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

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值