为什么这段代码说C :: f会覆盖A :: f而不是B :: f?

Lea*_*ath 4 c++

第3个代码示例中,注释说C :: f会覆盖A :: f.为什么是这样?我的直觉说它应该覆盖B :: f.

struct A { virtual void f(); };     // A::f is virtual
struct B : A { void f(); };         // B::f overrides A::f in B
struct C : virtual B { void f(); }; // C::f overrides A::f in C
struct D : virtual B {}; // D does not introduce an overrider, B::f is final in D
struct E : C, D  {       // E does not introduce an overrider, C::f is final in E
    using A::f; // not a function declaration, just makes A::f visible to lookup
};
int main() {
   E e;
   e.f();    // virtual call calls C::f, the final overrider in e
   e.E::f(); // non-virtual call calls A::f, which is visible in E
}
Run Code Online (Sandbox Code Playgroud)

use*_*353 6

Virtual Base类仅与数据成员相关,而不与方法相关.

无论是C::f覆盖A::f还是B::f- 它都是一样的.

该评论可以改为C::f覆盖B::f,它仍然意味着同样的事情.

考虑以下层次结构(无虚拟基类)

class A { virtual void foo(); }
class B : public A { void foo(); }
class C : public B { void foo(); }
Run Code Online (Sandbox Code Playgroud)

在这里,B::foo覆盖A::foo.C::foo覆盖B::foo.所以实际上,C::foo覆盖A::foo.

虚基类用于避免多个基类实例 - 但这仅与基类中的数据成员而不是方法相关.如果基类只有方法而没有数据成员,则根本不需要将其作为虚拟基类.


M.M*_*M.M 6

C++ 14标准的文本是(class.virtual/2):

如果虚拟成员函数vf在类Base和类中声明Derived,直接或间接地从具有相同名称Base的成员函数派生vf,参数类型列表,cv限定和ref-qualifier(或不存在相同)Base::vf声明,然后Derived::vf也是虚拟的(无论是否声明)并覆盖Base::vf.为方便起见,我们说任何虚函数都会覆盖自身.

所以C::f覆盖所有的A::f,B::fC::f.