【问题标题】:Why f2 in class B is overridden by f2 in class D为什么 B 类中的 f2 被 D 类中的 f2 覆盖
【发布时间】:2019-11-26 13:18:35
【问题描述】:

我无法理解孙子 (D) 如何覆盖隐藏的(通过 C::f2(A&) 方法 (B::f2(A))。

这是一个示例代码:

class B{
    public:
    virtual void f2(A a){cout<<"B::f2()"<<endl;}
};

class C:public B{
private:
    public:
    virtual void f2(A& a){cout<<"C::f2(A&)"<<endl;
    }

};

class D:public C{
    public:
    void f2(A a){cout<<"D::f2(A)"<<endl;}
};

int main(void)
{
    B* b = new D();
    A a2 = A();
    A &a = a2;
    b->f2(a); // prints D::f2 - should'nt it print B::f2??

    C* c = new D();
    c->f2(a); // prints C::f2 - as expected
    return 0;

}

【问题讨论】:

  • 检查这个:stackoverflow.com/questions/7098054/…D::f2 实际上是一个虚拟并覆盖 B::f2
  • 但是 C::f2 隐藏了 B::f2。
  • 不,它不会隐藏它。是什么让你认为它隐藏了它?
  • 虚函数覆盖的规则根本不考虑可见性。 (或访问:您也可以覆盖基类的虚拟私有函数。)不确定您在寻找什么其他类型的“为什么”。
  • @LightnessRacesinOrbit 当然。查找b-&gt;f2 找到B::f2 并调用它的最终覆盖器D::f2。查找 c-&gt;f2 会找到 C::f2,这是它自己的最终覆盖。

标签: c++ inheritance overriding virtual


【解决方案1】:

为什么 B 类中的 f2 被 D 类中的 f2 覆盖

因为D::f2 具有相同的参数列表。如果 base 中存在这样的虚函数,则具有相同名称和参数列表的函数会覆盖 base 中的虚函数。

虚函数是否被中间库中的另一个同名函数隐藏,对此没有影响。

标准中的规则(草案):

[class.virtual]

如果一个虚成员函数vf在类Base和类Derived中声明,直接或间接派生自Base,则成员函数vf同名,参数类型-list ([dcl.fct])、cv-qualification 和 ref-qualifier(或没有相同)作为 Base::vf 声明,然后 Derived::vf 覆盖 Base::vf

因此,总而言之,D::f2 会覆盖 B::f2,因为它具有相同的参数列表。它不会覆盖C::f2,因为参数列表不同。

【讨论】:

  • 函数在B*上调用。
  • The function is called on a B* 确实。而指向对象的动态类型为D
  • 哦,是的。在证明有 隐藏后,我把自己搞混了:D 在那之后有点忘了这个问题..
【解决方案2】:

B的接口没有f2( A&amp; ),所以如果编译器不做隐式转换,你的b-&gt;f2( a );会编译失败。

但是由于B 的接口确实有f2( A ),编译器会隐式地将您的aA&amp; 类型转换(*1) 到A 类型。所以,f2( A )形式的功能是从B的界面中选择出来的。

并且由于您的 D 覆盖了该函数,因此最终会调用 D 的函数。

(*1) C++ 顽固分子可能知道比“隐式转换”更具体的术语,以准确说明在这些情况下会发生什么。但我只是个业余爱好者。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-07
    • 1970-01-01
    相关资源
    最近更新 更多