我正在研究与多重继承相关的主题。我提出了以下代码,但无法完全弄清其背后的机制:

struct root
{
    virtual void vfunction(){ /* root version */ }
};

struct mid1:public root
{
    virtual void vfunction(){ /* mid1 version */ }
};

struct mid2:public root
{
    virtual void vfunction(){ /* mid2 version */ }
};

struct inheritMulti:public mid1, public mid2
{
    void ambiguityMethod(){
        vfunction();    // error: ambiguous
    }
    void method1(){
        mid1& t = *this;
        t.vfunction();
    }
    void method2(){
        mid2& t = *this;
        t.vfunction();
    }
};


ambiguityMethod显然是一个错误。但是,在method1method2中的函数调用使我感到困惑。它们也是虚拟函数调用,而t实际上是inheritMulti类型。因此他们应该调用inheritMultivfunction版本,但是由于inheritMulti没有自己的版本,所以我不知道会发生什么。事实证明,在method1中的呼叫称为mid1版本,而在method2中的呼叫称为mid2版本。它是未定义的东西,只发生在我的编译器上吗?如果没有,为什么它会这样工作? vtable如何处理这种情况?谢谢!



首先感谢您的帮助。我自己搜索过有关主题的文章,所以,我知道“钻石问题”。但我认为我的问题与此不同。我主要关心的是method1method2中“虚拟函数调用”的行为是标准定义还是未定义。在编译器中,它的行为类似于我上面提到的,但是标准所承诺的行为是吗?如果定义明确,为什么要分别调用mid1和'mid2'版本? (直观的想法是调用inheritMulti版本,因为t的类型实际上是inheritMulti。)而且,大多数编译器如何处理这种情况?奇怪的是,method1method2中的虚拟函数调用调用了不同的函数。再次感谢!

最佳答案

void method1(){
    mid1& t = *this;
    t.vfunction();
}


在这里,您要调用在vfunction中未定义的inheritMulti,因此它将搜索vfunction中最接近的定义,而该定义在mid1中存在。请参阅层次结构。

根-> Mid1-> inheritMulti

根目录->中2->继承多

同样的情况

`void method2(){
    mid2& t = *this;
    t.vfunction();
}


在这里,在mid2中也找到了最接近的定义,因此得到了输出。这些调用不是模棱两可的,因为两个结构都在其中创建了自己的vfunction副本。

inheritMulti将有两个名为mid1mid2的子对象,并且这些子对象中的每一个都维护自己的vtable指针。虽然您可能会认为

mid1& t1 = *this;


mid2& t2 = *this;

t1和t2都相同,但是请尝试这样做...

bool same = ((void*)t1) == ((void*)t2);  // Result false!


因为编译器在后面生成一些代码来调整指针以指向正确的对象。

关于c++ - 多态如何涉及多重继承?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31523742/

10-11 22:35