怎么解决菱形继承

文章讨论了C++中菱形继承导致的存储空间浪费和二义性问题,通过实例展示了如何使用虚继承解决这些问题,使子类只继承一次父类的父类,确保正确覆盖属性值。
摘要由CSDN通过智能技术生成

一、什么是菱形继承?

C++具备其他语言所没有的多继承特性,一个子类可以继承自多个父类,这些父类可能继承自相同的父类,从而就造成了菱形继承。

菱形继承的问题是,一个是浪费存储空间,一个是二义性。这些可以通过代码展示:

#include <iostream>
using namespace std;

class A
{
public:
    void func1();
    void func2();
    int num;
};

class B1 : public A
{
public:
    void func1();
};

class B2 : public A
{
public:
    void func2();
};

class C : public B1, public B2
{
};

int main()
{
    C c;
    c.B1::num = 1;
    c.B2::num = 2;
    cout << "c.B1::num " << c.B1::num << " c.B2::num " << c.B2::num << endl;
    return 0;
}

 运行结果:

c.B1::num 1 c.B2::num 2

期望的运行结果应该是两个num的打印值都是2,即在两次对num的赋值中,第2次赋值覆盖第一次赋的值,从运行结果来看,显然并不是这样的。

使用g++ -fdump-lang-class virtual-inheritance.cpp -o vi 这个命令来查看类的内存模型,其中,     -fdump-lang-class是gcc 8.0以上使用的命令,gcc 8.0以下使用的参数为-fdump-class-hierarchy,可以看出在Class C中,两个Class A的地址并不一样!Class C在构造的时候构造了两次Class A

解决这个问题的方法就是使用虚继承,即将代码中B1类,B2类的继承方式改为虚继承:

即将上述代码中的

class B1 : public A
class B2 : public A

改为

class B1 : virtual public A
class B2 : virtual public A

此时再来查看类的模型

此时可以清楚地看到在Class C中,两份A的地址是一样的!子类(C)只继承了一次父类的父类(A)。虚继承是通过虚表指针偏移来实现的。父类(B1 ,B2)的 vptr 都有到共同基类(A)的偏移量,从而让子类(C)在多继承时指向同一个父类的父类(A)

此时执行可执行文件 vi 进行验证,

执行结果:

c.B1::num 2 c.B2::num 2

符合预期!

  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值