c++多继承菱形继承

多继承是c++特有的,然而这个特有也使得C++的麻烦比较多点,例如像菱形继承的二义性问题等等。而像java、python这些面向对象语言仅支持单继承。

一.继承

继承是C++完成复用的手段

1.单继承模式图:

这里写图片描述

2.多继承:多继承是建立在单继承的基础之上的一种继承机制,也就是子类有多个直接父类,继承模式图如下:

这里写图片描述

3.菱形继承:菱形继承之所以叫菱形继承,它来源于它的继承关系模型,这是根据它的模型形象的说明,下面便是菱形继承模式图:这里写图片描述

从菱形继承中可以看到单继承、多继承,所以菱形继承才是这里的重点,也是菱形继承复杂之处,它的复杂也带来不少的问题,通过了解底层我们就会发现菱形继承的问题
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;
};

对象模型分析,如图所示:

这里写图片描述

内存储存分析:

这里写图片描述

不难看出,菱形继承中有俩个_a,上面我们的调用方式是对的原因在于 我们采用了类域限定符;那么当我们在下面这种场景下去调用_a时,势必会带来一些问题:
void test()
{
    D d;
    d._a=1;
    d._b=3;
    d._c=4;
    d._d=5;
}
①这段代码会出错,原因是访问_a时,不明确,因为编译器并不知道我们所访问的_a究竟是B还是C中的_a(二义性);②d对象中有俩个_a(B::_a && C::_a),造成资源的浪费(数据冗余);
对于这俩个缺点C++采用虚继承来解决。

2.虚继承

关键词virtual,将virtual加在继承方式前,如:class B:virtual public A;

代码如下:
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;
};

类B、C虚继承A类,这样就避免了在D类中出现二义性、数据冗余,那么他到底是怎样实现的呢?下面我们先来看一下对象模型,并进行分析:

这里写图片描述

当我们对d对象中B的_a进行操作时会发现,C对象中的_a也在改变而且和B中的一样,这就说明了B::_a和C::_a是同一个元素,先来看一下底层(内存)吧!

这里写图片描述

当我们将所有元素对应其地址时会发现,蓝色的框里的东西,它们代表什么呢?进一步分析,发现好像是一段地址,试着取地址试一下:

这里写图片描述

我们会发现在这段地址下储存了一个零,再往下看四个字节,它分别储存了一个 14000000(10进制为20)0c000000(10进制为12)我们会发现:这里写图片描述
如上图分析,我们可知虚继承这一机制,是通过虚基表指针和虚基表 实现的。

猜你喜欢

转载自blog.csdn.net/fangxiaxin/article/details/76285186