美文网首页C++
C++多重继承与虚继承

C++多重继承与虚继承

作者: 咻咻咻i | 来源:发表于2017-06-06 01:53 被阅读0次

多重继承

一个简单的例子(非虚拟)

class Top
{
    public: int a;
}; 
class Left : public Top
{ 
    public: int b;
}; 
class Right : public Top
{ 
    public: int c;
}; 
class Bottom : public Left, public Right
{ 
    public: int d;
};

使用UML图,我们可以把这个层次结构表示为:



注意Top被继承了两次。这意味着类型Bottom的一个实例bottom将有两个叫做a的元素(分别为bottom.Left::a 和 bottom.Right::a)。


Left、Right 和 Bottom在内存中是如何布局的,让我们先看一个简单的例子。Left
和 Right拥有如下的结构:

Left Right
Top::a Top::a
left::b right::c

请注意第一个属性是从Top继承下来的。这意味着在下面两条语句后

Left* left = new Left();
Top* top = left;

Left 和 Top指向了同一地址,我们可以把Left Object当成Top Object来使用(很明显,Right与此也类似)。那Buttom呢?GCC的建议如下:

Buttom
Left::Top::a
Left::b
Right::Top::a
Right::c
Bottom::d

如果我们提升Bottom指针,会发生什么事呢?

Bottom* bottom = new Bottom();
Left* left = bottom;

这段代码工作正常。我们可以把一个Bottom的对象当作一个Left对象来使用,因为两个类的内存部局是一样的。那么,如果将其提升为Right呢?会发生什么事?

Right* right = bottom;

为了执行这条语句,我们需要判断指针的值以便让它指向Bottom中对应的段。

Bottom
Left::Top::a
Left::b
right --> Right::Top::a
Right::c
Bottom::d

经过这一步,我们可以像操作正常Right对象一样使用right指针访问bottom。虽然,bottom与right现在指向两个不同的内存地址。出于完整性的缘故,思考一下执行下面这条语句时会出现什么状况。

Top* top = bottom;

是的,什么也没有。这条语句是有歧义的:编译器将会报错。

error: `Top' is an ambiguous base of `Bottom'

两种方式可以避免这样的歧义

Top* topL = (Left*) bottom;
Top* topR = (Right*) bottom;

执行这两条语句后,topL 和 left会指向同样的地址,topR 和 right也会指向同样的地址。


虚拟继承

为了避免重复继承Top,我们必须虚拟继承Top:

class Top
{ 
    public: int a;
}; 
class Left : virtual public Top
{ 
    public: int b;
}; 
class Right : virtual public Top
{ 
    public: int c;
}; 
class Bottom : public Left, public Right
{ 
    public: int d;
};

这就得到了如下的层次结构:



虽然从程序员的角度看,这也许更加的明显和简便,但从编译器的角度看,这就变得非常的复杂。重新考虑下Bottom的布局,可能是:

Bottom
Left::Top::a
Left::b
Right::c
Bottom::d

这个布局的优点是,布局的第一部分与Left的布局重叠了,这样我们就可以很容易的通过一个Left指针访问 Bottom类。


未完待续。。。
摘抄自 开源中国

相关文章

网友评论

    本文标题:C++多重继承与虚继承

    本文链接:https://www.haomeiwen.com/subject/wbzwfxtx.html