C++中关于菱形继承

   C++中的继承体系,有单继承、多继承、还有复杂的菱形继承,今天我们只讨论菱形继承,以及菱形继承存在的问题,最后我们针对问题给出解决方案。

(1)什么是菱形继承?
       顾名思义,菱形继承就是,几个类的继承关系呈菱形状。为此,我们举例解释:
题目:有4个类,Person类、Student类、Teacher类、Assistant类,Student、Teacher继承Person,Assistant继承Student、Teacher。
具体继承关系,以及菱形继承对象模型如下图:



由以上两个图和各个类中的成员,我们会发现菱形继承存在一定的问题:
(1)当创建一个D的对象d时,由于D同时继承了B,C,而B,C都有从A继承过来
的成员_name,即我们要对d中的_name操作时,无法判断是B,C谁的成员,这个问题叫做
菱形继承的二义性
(2)假如说,A中的某一个成员被B,C继承之后,就想当成同一个变量使用,那么
就会有同一个变量才B,C存了2份的情况,这就造成了空间浪费,这个问题就
称为菱形继承的数据冗余

解决二义性的问题倒是有个简单的办法,就是在访问具体变量的时候,前面加上作用域解析符(::),但是要想同时解决二义性,数据冗余,我们提出一个另外一个方法,即虚继承;虚继承就是在有争议的变量的类的继承体系中,继承方式关键字前面加关键字virtual;本例中,就是Student、Teacher虚继承Person

那么,虚继承是怎么解决以上问题呢?
为了简单明了解释这个问题,我们再举个例子:4个类,A类,B类,C类,D类,继承关系如下图:


以上几个类继承的代码实现如下:

#include <iostream>
using namespace std;

class A
{
public:
	int a;
};

class B: public A
{
public:
	int b;
};

class C: public A
{
public:
	int c;
};

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

void test()
{
	D d;
	d.B::a=1;
	d.C::a=2;
	d.b=3;
	d.c=4;
	d.d=5;
	cout<<"q"<<endl;
}

int main()
{
	test();
	return 0;
}
        通过对比正常的菱形继承,加了虚继承之后D对象d内存情况,我们发现经过虚继承之后,类A中之前那个有争议的成员变量,不在分别自B,C中各存一份,而是在B,C中
都存了一份神秘的地址,在地址里存了这个成员变量的相对偏移量,通过这个偏移量即可找到这个公共的成员变量a;另外,虚继承之后,给公共的成员变量赋值,最后一个有效;以下是验证结果图(图1为没有虚继承的d的内存;图2为有虚继承的d的内存)

          图1   图2



菱形继承是指在一个继承体系,子类同时继承了两个不同的父类,而这两个父类又是同一个基类的派生类。这种继承关系形成了一个菱形的结构,因此得名菱形继承。 在 C++ 菱形继承可以通过以下步骤使用: 1. 定义基类:首先,定义一个基类,其包含一些共有的成员和方法。 ```cpp class Base { public: // 共有成员和方法 }; ``` 2. 定义第一个派生类:接下来,定义第一个派生类,它公有地继承自基类。 ```cpp class Derived1 : public Base { public: // 派生类成员和方法 }; ``` 3. 定义第二个派生类:然后,定义第二个派生类,它也公有地继承自基类。 ```cpp class Derived2 : public Base { public: // 派生类成员和方法 }; ``` 4. 定义菱形子类:最后,定义菱形子类,它同时继承自第一个和第二个派生类。 ```cpp class Diamond : public Derived1, public Derived2 { public: // 菱形子类成员和方法 }; ``` 这样,菱形子类 Diamond 就同时继承了 Derived1 和 Derived2 这两个派生类,而这两个派生类又继承自同一个基类 Base,形成了菱形继承的结构。 需要注意的是,在菱形继承,由于 Diamond 同时继承了 Derived1 和 Derived2,而这两个派生类都继承了 Base,所以 Diamond 可能存在对 Base 成员的二义性。为了解决这个问题,可以使用作用域限定符来明确指定访问哪个基类的成员,或者使用虚继承(virtual inheritance)来避免二义性问题。 以上是使用菱形继承的基本步骤和注意事项,希望能对你有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值