c++ - 多态性如何涉及多重继承?

标签 c++ polymorphism multiple-inheritance virtual-functions vtable

我现在正在研究与多重继承相关的主题。我想出了下面的代码,并不能完全弄清楚它背后的机制:

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类型。所以他们应该调用 vfunctioninheritMulti 版本,但是由于 inheritMulti 没有自己的版本,我不知道会发生什么.结果 method1 中的调用调用了 mid1 版本,而 method2 中的调用调用了 mid2 版本.它是未定义的并且只发生在我的编译器上吗?如果不是,为什么它会这样工作? vtable 是如何处理这种情况的呢?谢谢!


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

最佳答案

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

这里你调用的 vfunction 没有在 inheritMulti 中定义,因此它将搜索最近的 vfunction 定义,并且它存在在 mid1 中。查看层次结构。

Root->Mid1->inheritMulti

Root->Mid2->inheritMulti

同样

`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/

相关文章:

c++ - ROS catkin项目链接Qhull C++接口(interface)失败

c++ - 我们可以分配一个 unsigned int 变量,0xFULL 文字吗

c++ - 我需要一个何时使用非虚拟多重继承的简单示例

c++ - 在 C++ 中循环遍历 3d 索引的 1d 数组

c++ - 如何使 "whose type uses the anonymous namespace [-Werror]"gcc 版本 4.8.2 静音

types - 如何为角色组编写模块?

java - java层次结构不明确

java - 使用Java反射和泛型: can a method specify an actual type as its return value?

c++ - 纯虚继承、多重继承、C4505

c# - 多重继承的解决方案 - 有机会改变保护级别