【C++】菱形继承问题、组合


一、菱形继承是什么?

在C++中存在多继承,即一个子类可以继承于多个父类,此时如果继承的父类又同时继承一个父类,那么就会引起菱形继承,继承结构如下图所示:
在这里插入图片描述
代码表示:

class A
{
public:
    A(const string& name = "", int age = 0)
        :_name(name),
        _age(age)
    {}
protected:
    string _name;
    int _age;
};

class B : public A
{
public:
    B(const string& name = "", int age = 0, int id = 0)
        :A(name, age),
        _id(id)
    {}
protected:
    int _id;
};

class C : public A
{
public:
    C(const string& name = "", int age = 0, const string& sex = "")
        :A(name, age),
        _sex(sex)
    {}
protected:
    string _sex;
};

class D : public B, public C
{
public:
    D(const string& name = "", int age = 0, int id = 0, const string& sex = "", const string& hobby = "")
        :B(name, age, id),
        C(name, age, sex),
        _hobby(hobby)
    {}
protected:
    string _hobby;
};

知道了什么是菱形继承,那么菱形继承有什么危害呢?菱形继承造成了数据的二义性和降低了性能,通过上面的代码可以知道,B、C都继承自A,那么B、C中都各有一份_name和_age,此时D再同时继承于B、C,那么D中不就有两份_name和_age了吗,这不是我们所期望看到的,虽然是可以通过指定类域的方法来区别使用父类中的数据:

B::_name
C::_name

但这并不合理,如果说一个人可以拥有多个名字,但是年龄、性别、身份证号码这些固定的属性通过菱形继承获得了多份,这就不合适了。

二、虚继承

那么菱形继承该如何解决呢?此时就引入了虚继承,现来看一下虚继承怎么用:

class A
{
public:
    int _a;
};

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

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

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

在继承方式前面加上 virtual 即可,此时该继承就是虚继承,来看一些不是虚继承的内存是怎样的:
在这里插入图片描述
可以看到在继承的B、C中各自有各自继承自A的值,而虚继承下的内存又是怎样的呢?如下:
在这里插入图片描述
可以看到在继承的B、C中只存了自己本身的值,而另外存了一个地址,来看看该地址所指向的内容是什么:
在这里插入图片描述
以上是B中所存的地址中指向的内容,通过该地址我们找到了一块区域,该区域内的14转换为十进制就是20,20表示的是从0x00B8FB5C该位置到0x00B8FB70的偏移量,C中也是同样的,也就是说想要找到B中继承自A的值,直接通过偏移量就可以了,此时数据不存在二义性,因为只有一份。

三、组合

如果说继承是is a的关系,那么组合就是has a的关系,即在一个类中存在另外一个类作为成员变量,代码表示:

class A
{
public:
	void func();
protected:
    int _a;
};

class B
{
private:
    A _a;
    int _b;
};

以上就是一个组合,B可以直接使用A中的公开函数func(),根据func()的实现也可以间接使用保护成员_a,组合相比继承存在一点优势,打个比方,如果以上代码是继承,那么B继承于A,B可以直接使用A中的公开和保护成员,那么如果此时A修改了_a的名字,而B又使用了_a,那么B也要跟着修改,而对于组合来说并没有影响,总的来说就是组合相对于继承的优势就是低耦合、高内聚。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值