美文网首页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