虚拟多重继承 - 最终超控器(Virtual multiple inheritance - fina

2019-06-23 15:38发布

而试图在C更大的深度继承机制来分析++我偶然发现了下面的例子:

#include<iostream>

using namespace std;

class Base {
public:
    virtual void f(){
    cout << "Base.f" << endl; 
    }
};

class Left : public virtual Base {    
};

class Right : public virtual Base{
public:
    virtual void f(){
        cout << "Right.f" << endl; 
    }
};

class Bottom : public Left, public Right{

};

int main(int argc,char **argv)
{
    Bottom* b = new Bottom();
    b->f();
}

以上,不知何故,编译并调用右键:: F()。 我看看有什么可以在编译器怎么回事,它的理解是有一个共享的基本对象,而右覆盖F(),但实际上,在我的理解,应该有两种方法: Left::f()从继承Base::f() )和Right::f() ,它覆盖Base::f() 。 现在,我认为,基于有由底部被继承两种不同的方法,都与相同的签名,应该有一个冲突。

任何人都可以解释的C ++与该情况下的交易,其说明书的细节和它如何它从低级别的透视?

Answer 1:

可怕钻石有一个单一的基础上,从所述两个中间对象导出,然后将第四类型的关闭与从两种类型中的中间水平多重继承的金刚石。

你的问题似乎是多少f功能在前面的例子中声明? 答案是一个。

让我们开始只是基类和派生的线性分级的简单示例:

struct base {
   virtual void f() {}
};
struct derived : base {
   virtual void f() {}
};

在这个例子中有一个单一的f申报其中有两个覆盖, base::fderived::f 。 在类型的对象derived ,最终的置换器被derived::f 。 需要注意的是两个很重要的f功能表示有多种实现单一功能。

现在,回到最初的例子,上线在右边, Base::fRight::f都以同样的方式被覆盖了相同的功能。 因此,对于类型的对象Right ,最终置换器是Right::f 。 现在对于类型的最终目标Left ,最终置换器是Base::f作为Left没有覆盖的功能。

当金刚石是封闭的,并且因为继承是virtual存在单个Base对象,即声明了一个f功能。 在继承的第二个层次, Right将覆盖该功能与它自己的实现,这是为最派生类型最终置换器Bottom

你可能想看看这外面的标准,并看看如何实际上是由编译器来实现。 编译器,从而在当Base物体它增加了一个隐藏指针vptr到虚拟表。 虚拟表保存指针的thunk(为简单起见只是假设,表中保存指针的函数的最后overriders,[1])。 在这种情况下, Base对象将不包含成员数据和只是一个指向具有指向功能的表Base::f

Left延伸Base ,用于创建一个新的V Left和在虚函数表的指针被设置到的最终超控器f在这个水平上,这是顺便Base::f所以在两者的vtables指针(忽略蹦床)跳转到相同的实际执行情况。 当类型的对象Left被构建,所述Base子对象首先被初始化,然后前成员初始化Left (如果有)的Base::vptr指针被更新为指Left::vtable (即存储在指针Base是指用于定义的表Left )。

在钻石的另一面,那就是为创建虚函数表Right包含结束调用一个thunk的 Right::f 。 如果类型的对象Right是要创建相同的初始化过程中会发生与Base::vptr将指向Derived::f

现在,我们得到的最终目标Bottom 。 再次,针对类型生成一个虚函数表Bottom和虚函数表,如在所有其他的情况下,包含表示单个条目f 。 编译器分析继承层次结构,并且确定Right::f覆盖Base::f ,并且不存在等效覆盖左侧分支,因此,在Bottom的VTable表示指针fRight::f 。 再次,在施工过程中Bottom物,该Base::vptr被更新为指Bottom的VTable。

正如你看到的,所有四个虚函数表有一个条目f ,有一个单一的 f在节目中,即使储存在每个虚函数表的值是不同的(最终overriders不同)。

[1]所述的thunk是一小块代码,适应this指针如果需要的话(多重继承通常意味着它需要),然后将呼叫转发到实际倍率。 在单继承的情况下, this指针并不需要更新,并在thunk消失,直接指向实际功能的虚函数表的条目。



文章来源: Virtual multiple inheritance - final overrider