2017-09-27 165 views
41

例如:重写纯虚函数时,有没有使用`override`的意思?

class Base { 
    virtual void my_function() = 0; 
}; 

class Derived : Base { 
    void my_function() override; 
}; 

从我读的override关键字用来确保我们有在我们覆盖的功能正确的签名,这似乎是其唯一的用途。

然而,在一个纯虚函数的情况下,编译器会如果我们在派生类中使用了不正确的签名(或基类,这取决于一个人如何看待事物)抛出一个错误。那么,Derived::my_function()声明的末尾是否还有点加override

+4

请注意,抽象*传播*。如果你在'Derived'类中提供了错误的签名,那么'Derived'类也变得很抽象。如果没有'override'关键字,可能无法在正确的位置检测到。 –

+4

它确保如果基类与“override”断言不兼容,您的代码将无法编译。 – EJP

+1

“penning有针对性的教学程序传播优先编程实践” - T.J.Elgan – coderatchet

回答

67

However, in the case of a pure virtual function, the compiler would throw an error if we used an incorrect signature in the Derived class

不,这编译:

class Base { 
    virtual void my_function() = 0; 
}; 

class Derived : Base { 
    void my_function(int); 
//     ^^^ mistake! 
}; 

虽然这并不:

class Base { 
    virtual void my_function() = 0; 
}; 

class Derived : Base { 
    void my_function(int) override; 
}; 

error: void Derived::my_function(int) marked override , but does not override


你在谈论只有实例Derived时出现的错误 - override允许y ou早点发现错误,并使得定义更清晰/更具可读性。

+0

您可以将运行时错误添加到另一个类中,并在保留纯虚拟的同时实现'Base :: my_function'。 – Yakk

+3

等等,所以有一个点?你继续谈论它是如何有用的,但只是从“不”开始。 – snb

+10

“否”是为了响应编译器抛出错误的声明。 –

30

是的,这是坚持用override关键字作为一个防御性的做法是一个好主意。

Base的作者确定my_function不再是纯虚拟的时候,应考虑进行重新设计,并且应该采用新的参数。使用override,编译器会捕获这个问题;没有override你的Derived类将继续编译。

7

是!

它提高代码清晰度override关键字防止模糊和传送它的覆盖它的基类的方法的意义。

防止可能出现的意外的使用: 在将来,如果基类变化方法签名(这里virtual),它迫使派生类来相应地改变。 (带有编译器错误)。否则(不带override关键字)可能会被视为method overload,这不是预期的。

+0

虽然它不会因为正常隐藏而导致方法过载 – RiaD

3

通常不与override烦心事就在移动的错误。我发现更好地获取错误的位置 - 在定义无法覆盖的方法时,而不是在实例化类时。

但是,有这个防止运行时错误的方式。

struct Base { 
    virtual void foo(int x = 0) = 0; 

    void foo(double d) { 
     foo((int)d); 
    } 
}; 
inline void Base::foo(int x) { std::cout << "Default foo(" << x << ")\n"; } 

struct Derived:Base { 
    using Base::foo; 
    virtual void foo() { // oops, no int! 
    std::cout << "Derived::foo()\n"; 
    Base::foo(); 
    } 
}; 
struct Derived2:Derived { 
    virtual void foo(int x=0) override { 
    std::cout << "Derived2::foo()\n"; 
    Derived::foo(x); 
    } 
}; 

这里我们打算每个foo调用其父foo。但由于Derived::foo不覆盖与Base::foo相同的签名,因此不会调用它。

添加overridefoo()Derived之后,我们得到编译时错误。

是的,我实现了纯虚函数Base::foo