'override'关键字只是检查重写的虚方法吗?

aia*_*iao 210 c++ inheritance overriding virtual-functions c++11

据我所知,override在C++ 11中引入关键字只不过是一个检查,以确保正在实现overridevirtual函数是基类中的函数.

是吗?

Ker*_* SB 241

这确实是个主意.关键是你明确你的意思,以便可以诊断出一个无声的错误:

struct Base
{
    virtual int foo() const;
};

struct Derived : Base
{
    virtual int foo()   // whoops!
    {
       // ...
    }
};
Run Code Online (Sandbox Code Playgroud)

上面的代码编译,但不是你的意思(注意缺少const).如果你反而说virtual int foo() override,那么你会得到一个编译错误,你的函数实际上并没有覆盖任何东西.

  • +1:不幸的是,当人们建议新的"覆盖"功能"修复"这个时,它有点像红色鲱鱼; 你必须记得使用它,就像你应该记得写'const`;) (72认同)
  • @LightnessRacesinOrbit:是的,这不是万无一失的; 然而,记住一个一般规则(当有人打算去写"覆盖"时)比记住角落情况更有可能,即复制不同原型的函数没有普遍性,只有像缺少`const`或写`char'的不规则性.而不是`int`等 (15认同)
  • @Light,[这个答案](http://stackoverflow.com/a/29290293/514235)中提到了“override”说明符的最佳用例,它比直接的更具有未来感。答案表明,使用“virtual”方法保留“override”。将来,当有人错误地更改签名时,它的用处就会发挥作用。 (2认同)
  • 核心准则 C.128 规定“虚拟函数应准确指定 virtual、override 或 Final 之一”。https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rh-override (2认同)

use*_*631 33

维基百科报价:

覆盖特殊标识符意味着编译器将检查基类以查看是否存在具有此确切签名的虚函数.如果没有,编译器将会出错.

http://en.wikipedia.org/wiki/C%2B%2B11#Explicit_overrides_and_final

编辑(试图提高答案):

将方法声明为"覆盖"意味着该方法旨在重写基类上的(虚拟)方法.重写方法必须具有与要重写的方法相同的签名(至少对于输入参数).

为什么这有必要?好吧,以下两个常见错误案例被阻止:

  1. 一个错误输入新方法中的类型.编译器不知道它打算编写前一个方法,只是将它作为新方法添加到类中.问题是旧方法仍然存在,新方法只是作为重载添加.在这种情况下,对旧方法的所有调用都将像以前一样运行,而不会改变行为(这将是重写的目的).

  2. 一个忘记将超类中的方法声明为"虚拟",但仍尝试在子类中重写它.虽然这显然会被接受,但行为并不完全符合预期:该方法不是虚拟的,因此通过指向超类的指针访问将结束调用旧(超类')方法而不是新(子类')方法.

添加"覆盖"清楚地消除了歧义:通过这个,人们告诉编译器有三件事需要:

  1. 在超类中有一个具有相同名称的方法
  2. 超类中的此方法被声明为"虚拟"(这意味着,意图重写)
  3. 超类中的方法与子类中的方法(重写方法)具有相同的(input*)签名

如果其中任何一个为假,则发出错误信号.

*注意:输出参数有时不同,但相关类型.如果感兴趣,请阅读有关协变和逆变换的信息.


小智 27

当有人更新基类虚方法签名(例如添加可选参数但忘记更新派生类方法签名)时,发现" 覆盖 "非常有用.在这种情况下,基类和派生类之间的方法不再是多态关系.没有覆盖声明,很难找到这种bug.


Ron*_*ell 5

是的,就是这样.这是一个检查,以确保一个人不会尝试覆盖并通过一个拙劣的签名弄乱它.这是一个维基页面,详细解释了这一点,并有一个简短的说明性示例:

http://en.wikipedia.org/wiki/C%2B%2B11#Explicit_overrides_and_final