虚拟功能背景下的主导地位是什么?

时间:2014-11-10 22:49:18

标签: c++ c++11 language-lawyer virtual-functions virtual-inheritance

代码示例:

考虑以下钻石层次结构:

struct A
{
    virtual void f(){}
    void g(){}
};    
struct B : virtual A
{
    virtual void f() override{}
    void g(){}
};     
struct C : virtual A
{   
};    
struct D: B, C
{    
};

int main()
{
    D d;
    d.f(); //B::f is called
    d.g(); //B::g is called
}

我的理解:

就非虚拟函数g而言,一切都很清楚:名称B::g隐藏A::g,即使名称A::g可以在没有通过C隐藏。没有含糊之处。调用B::gThe standard在10.2 p.10中明确证实了这一点:

  

[注意:当使用虚拟基类时,可以沿着通过的路径到达隐藏声明   不通过隐藏声明的子对象网格。这不是含糊不清的。相同的   使用非虚拟基类是一种模糊性;在这种情况下,没有唯一的名称实例   隐藏所有其他人。 - 尾注] [例子:

此外,this answer对相关问题提供了对此问题的详尽解释。

问题:

我不明白上面提到的引用与虚函数f的关系。 f没有涉及名称隐藏,是吗?只涉及覆盖,10.3 p.2读取:

  

类对象S的虚拟成员函数C :: vf是final   除非最大的派生类(1.8)是S的基础,否则覆盖   class subobject(如果有)声明或继承另一个成员函数   这会覆盖vf。在派生类中,如果是虚拟成员函数   基类子对象有多个最终覆盖程序   是不正确的。

现在,在我看来,虚函数f完全符合具有最终覆盖的的定义,并且程序应该是格式错误的。但事实并非如此。或者是吗? MSVC编译得很好,有以下警告:

  

警告C4250:' D' :继承' B :: B :: f'通过支配地位

说实话,我从来没有遇到过这样的术语"支配地位"之前。当我在标准中搜索它时,它在索引中只出现一次,并引用我的第一个引用来自的章节。并且,正如我已经提到的,引用似乎只与名称隐藏而不是虚函数覆盖有关。

问题:

  • f在D中有多个最终覆盖?
  • 在这种情况下支配的规则是否适用?它是如何遵循标准的?

1 个答案:

答案 0 :(得分:5)

我再次引用[10.3]/2

  

类对象C::vf的虚拟成员函数S最终覆盖,除非S为基数的派生类(1.8)最多class subobject(如果有)声明或继承覆盖vf的另一个成员函数。在派生类中,如果基类子对象的虚拟成员函数具有多个最终覆盖,则程序格式不正确。

因此,在您的示例中,A::f不是最终的覆盖者,因为D(派生程度最高的类)继承了覆盖它的B::fB::f是最后的覆盖者,所以它被调用。

如果有多个最终覆盖者(例如,如果C也覆盖f),该程序将是格式错误的,但只有一个,所以一切都很好。

Clang和GCC编译此without a single warning

回答你的问题,the documentation on C4250 warning完全描述了你的情况,并且通过支配它显然意味着[10.3]/2中描述的行为。