据我所知,在c++ 11中引入override关键字不过是检查,以确保正在实现的函数是基类中的虚函数的重写。

就是这样吗?


当前回答

这就是我的想法。关键是你要明确你的意思,这样就可以诊断出一个无声的错误:

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

struct Derived : Base
{
    virtual int foo()   // whoops!
    {
       // ...
    }
};

上面的代码可以编译,但不是您想要的(注意缺少const)。如果你说virtual int foo() override,那么你会得到一个编译器错误,你的函数实际上没有覆盖任何东西。

其他回答

是的,是这样。这是一种检查,以确保有人不会试图重写,并通过拙劣的签名把事情搞砸。这里有一个Wiki页面详细解释了这一点,并有一个简短的说明性示例:

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

维基百科:

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

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

编辑(试图改进一下答案):

将一个方法声明为“override”意味着该方法打算重写基类上的(虚)方法。重写方法必须具有与其打算重写的方法相同的签名(至少对于输入参数而言)。

为什么这是必要的?好了,下面两种常见的错误情况都避免了:

one mistypes a type in the new method. The compiler, unaware that it is intending to write a previous method, simply adds it to the class as a new method. The problem is that the old method is still there, the new one is added just as an overload. In this case, all calls towards the old method will function just as before, without any change in behavior (which would have been the very purpose of the rewriting). one forgets to declare the method in the superclass as "virtual", but still attempts to re-write it in a subclass. While this will be apparently accepted, the behavior won't be exactly as intended: the method is not virtual, so access through pointers towards the superclass will end calling the old (superclass') method instead of the new (subclass') method.

添加"override"清楚地消除了歧义:通过这个,一个是告诉编译器需要做三件事:

在超类中有一个同名的方法 超类中的这个方法被声明为“virtual”(这意味着要重写)。 父类中的方法与子类中的方法(重写方法)具有相同的(input*)签名。

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

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

这就是我的想法。关键是你要明确你的意思,这样就可以诊断出一个无声的错误:

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

struct Derived : Base
{
    virtual int foo()   // whoops!
    {
       // ...
    }
};

上面的代码可以编译,但不是您想要的(注意缺少const)。如果你说virtual int foo() override,那么你会得到一个编译器错误,你的函数实际上没有覆盖任何东西。

c++ 17标准草案

在浏览了c++ 17 N4659标准草案上的所有覆盖点之后,我能找到的唯一关于覆盖标识符的参考是:

类的成员函数被标记为virt-说明符override且不重写 基类时,程序是病态形式的。(例子: 结构B { 虚空f(int); }; 结构体D: B { 虚拟无效f(长)覆盖;//错误签名覆盖B::f 虚拟无效f(int)覆盖;/ /好吧 } - end示例]

所以我认为可能炸毁错误的程序实际上是唯一的影响。

发现“override”是有用的,当有人更新基类的虚方法签名,如添加可选参数,但忘记更新派生类的方法签名。在这种情况下,基类和派生类之间的方法不再是多态关系。如果没有覆盖声明,就很难发现这类错误。