C++中关于菱形继承

来源:互联网 发布:知乎社区 官网 编辑:程序博客网 时间:2024/06/10 01:56

   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



原创粉丝点击