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

Arm*_*yan 6 c++ virtual-functions virtual-inheritance language-lawyer c++11

代码示例:

考虑以下菱形层次结构:

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
}
Run Code Online (Sandbox Code Playgroud)

我的理解:

就非虚拟功能g而言,一切都很清楚:名称B::g隐藏A::g,即使名称A::g可以在不被隐藏的情况下到达C.没有含糊之处.B::g叫做.该标准在10.2 p.10中明确证实了这一点:

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

此外,对相关问题的这个答案提供了对该问题的详尽解释.

问题:

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

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

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

警告C4250:'D':通过优势继承'B :: B :: f'

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

问题:

  • 是否f有d不止一个最终置换器?
  • 在这种情况下,支配地位的规则是否适用?它是如何遵循标准的?

Ant*_*vin 5

[10.3]/2再说一遍:

除非最大派生类(1.8)是基类子对象(如果有)声明或继承覆盖的另一个成员函数,否则C::vf类对象的虚拟成员函数S最终S覆盖vf.在派生类中,如果基类子对象的虚拟成员函数具有多个最终覆盖,则程序是格式错误的.

因此,在您的示例A::f中,不是最终的覆盖,因为D(最派生的类)继承B::f覆盖它.B::f是最终的覆盖者,所以它被称为.

如果有一个以上的最终覆盖(例如,如果C也是覆盖f),该程序将是不正确的,但只有一个,所以一切都很好.

Clang和GCC在没有一个警告的情况下编译它.

回答你的问题,关于C4250警告的文档准确地描述了你的情况,并且通过支配它显然意味着所描述的行为[10.3]/2.