菱形继承问题分析及其在C++的解决方法(虚继承)

菱形继承问题分析及其在C++的解决方法(虚继承)

定义

面向对象语言都有一种特性–继承
但存在一种场景(多继承)会掉入陷阱,图示与代码如下:
image
代码如下

class Person
{
    int weight;
public:
    int getWeight()
    {
        return weight;
    }
};
class A : public Person {};
class B : public Person {};
class C : public A, public B {};

int main()
{
    C c;
    int weight = c.getWeight();//此代码不会被任意编译器通过
    return 0;
}

如上代码所示,编译器并不会通过以上代码
注释掉报错代码,调试可见
image
不能通过编译主要包括两方面问题

  • 二义性
    在对象c调用weight时,如果单继承很简单,但在多继承中,该对象不知道应调用A,B哪一个类下的weight,此为二义性
  • 数据冗余
    c只需要一个weight,实际上其拥有两个重复的值,此为数据冗余

虽然通过作用域操作符::可以解决,但c++还提供了更主流的解决方案–虚继承

虚继承

通过虚继承,无论该类作为派生类出现多少次,只能继承一个共享的基类子对象 使用时,通过virtual声明继承关系即可

对于以上代码,应将

class A : public Person {};
class B : public Person {};

改成

class A : virtual public Person {};
class B : virtual public Person {};

代码即可通过

值得强调的是

  • 虚继承会带来可读性与执行性能的下降
  • 虚继承的底层实现牵扯到概念–虚基表,简单解释如下。 执行sizeof(c),vs 32位输出8
    虚继承后输出12,对象c实际空间使用了虚基表
    对象c的空间占用,如图
    image
    对虚基表更详细的介绍,见另一篇博客。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值