【C++ 继承】关于多继承、菱形继承你了解多少?

1. 为什么 C++ 有多继承,Java 没有多继承呢?

C++ 实现多继承是为了满足某些场景的需要,但是有多继承就一定会有 菱形继承的情况,菱形继承会导致数据冗余和二义性问题,所以菱形继承需要避免,这是一个bug,所以Java为了避免菱形继承,通过单继承和接口来实现,没有多继承。

2. 什么是菱形继承呢?

  • ① 如下图所示,就是一个菱形继承,注意❗:菱形继承不代表一定要满足菱形。
  • ② 一个派生类同时继承自两个或多个基类,而这些基类又继承自同一个共同的基类,形成了一个菱形的继承结构。
    在这里插入图片描述

3. 菱形继承产生数据冗余和二义性问题

数据冗余:
① 如下图所示,明明是同一个人,却存了两个名字;

② 菱形继承可能会造成重复存储相同的成员变量,增加了内存消耗;

二义性:
① 当研究生助理为学生的时候,他叫小张,当他为老师的时候,他又叫张老师,那么此时就会存在一个问题,他到底叫什么呢?

② 如果派生类继承的两个基类都有相同的函数,并且派生类中没有对这些函数进行覆盖或隐藏,那么在派生类中调用这些函数时,编译器无法确定要调用哪个版本的函数,从而导致二义性。

在这里插入图片描述

  • 如何解决菱形继承问题的呢?

在 C++ 中,可以通过虚继承(Virtual Inheritance)来解决菱形继承所带来的数据冗余和二义性问题。虚继承是一种特殊的继承方式,可以确保共同基类在派生类中只有一份实例,从而避免了数据冗余和二义性问题。

在这里插入图片描述

  • 为了研究虚拟继承原理,我们给出了一个简化的菱形继承继承体系,再借助内存窗口观察对象成
    员的模型。
#include <iostream>

using namespace std;

class A
{
public:
	int _a;
};


// class B : public A
class B : virtual public A
{
public:
	int _b;
};


// class C : public A
class C : virtual public A
{
public:
	int _c;
};


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


int main()
{
	D d;
	d.B::_a = 1;
	d.C::_a = 2;
	d._b = 3;
	d._c = 4;
	d._d = 5;

	return 0;
}

在这里插入图片描述

  • 下图是菱形虚拟继承的内存对象成员模型:这里可以分析出D对象中将A放到的了对象组成的最下
    面,这个A同时属于B和C,那么B和C如何去找到公共的A呢?这里是通过了B和C的两个指针,指
    向的一张表。这两个指针叫虚基表指针,这两个表叫虚基表。虚基表中存的偏移量。通过偏移量
    可以找到下面的A。
    在这里插入图片描述
  • 下面是Person关系菱形虚拟继承的原理解释:
    在这里插入图片描述
  • 13
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

未来可期LJ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值