关于C++中的虚函数覆盖

Gho*_*ade 0 c++ polymorphism virtual inheritance overriding

我对以下情况有点困惑,它们是否是正确的覆盖功能copy但没有超载的方法,或者它们都是正确的?

class Base{
public:
    virtual Base* copy(Base* b){...}
};

class Derived:public Base{
public:
    virtual Base* copy(Base* b){...}//I know this should work
 // but how about the followings?
    //virtual Base* copy(Derived* b){...}
    //virtual Derived* copy(Base* b){...}
    //virtual Derived* copy(Derived* b){...}
};
Run Code Online (Sandbox Code Playgroud)

顺便说一下,访问权限的变化是否会有所不同?比如,我像这样编写Derived类:

class Derived:public Base{
private://or protected:
    virtual Base* copy(Base* b){...}
    ...
};
Run Code Online (Sandbox Code Playgroud)

Lig*_*ica 6

这些是函数覆盖的规则:

[C++11: 10.3/2]:如果vf在类Base和类中声明虚拟成员函数Derived,直接或间接地从具有相同名称Base的成员函数派生,参数类型列表(8.3.5),cv-qualification和ref-qualifier(或如果没有声明,那么它也是虚拟的(无论是否如此声明)并且它会覆盖111.[..]vfBase::vfDerived::vf Base::vf

如果不满足这些规则,则新函数不会覆盖旧函数(尽管它可能会重载隐藏它).

所以:

class Base
{
public:
    virtual Base* copy(Base* b);
};

class Derived : public Base
{
public:
    // Overrides Base::copy
    virtual Base* copy(Base* b);

    // Does NOT override Base::copy (due to different parameter-type-list)
    virtual Base* copy(Derived* b);

    // Overrides Base::copy (despite different return type)
    virtual Derived* copy(Base* b);

    // Does NOT override Base::copy (due to different parameter-type-list)
    virtual Derived* copy(Derived* b);

private:
    // Overrides Base::copy (despite different access specifier)
    virtual Base* copy(Base* b);
};
Run Code Online (Sandbox Code Playgroud)

但是,请注意上述类别Derived实际上是不正确的,因为其结束10.3/2状态:

在派生类中,如果基类子对象的虚拟成员函数具有多个最终覆盖,则程序是格式错误的.

这意味着我们应该只声明其中一个重要的功能.我将它们全部列在单个类定义中仅用于说明目的.

virtual Derived* copy(Base* b)覆盖可能会令人惊讶Base::copy,因为它具有不同的返回类型; 只要两个返回类型是协变的,就允许这样做:

[C++11: 10.3/7]: 重写函数的返回类型应与重写函数的返回类型相同或与函数类的协变相同.如果函数D::f覆盖函数B::f,则函数的返回类型如果满足以下条件则是协变的:

  • 两者都是类的指针,都是对类的左值引用,或者两者都是对类的右值引用
  • 返回类型中的类与返回类型中B::f的类是同一个类D::f,或者是返回类型中类的明确且可访问的直接或间接基类D::f
  • 指针或引用具有相同的cv限定,并且返回类型中的类类型D::f具有与返回类型中的类类型相同的cv-qualification或更少的cv-qualification B::f.

至于publicvs private问题,没有规则说这很重要; 如有任何疑问,请在脚注111中澄清情况:

111具有相同名称但不同参数列表(第13条)作为虚函数的函数不一定是虚拟的,也不会覆盖.virtual在覆盖函数的声明中使用说明符是合法的但是冗余的(具有空语义).在确定覆盖时不考虑访问控制(第11条).