问题
As I understand it, the override keyword states that a given declaration implements a base virtual method, and the compilation should fail if there is no matching base method found.
My understanding of the final keyword is that it tells the compiler that no class shall override this virtual function.
So is override final redundant? It seems to compile fine. What information does override final convey that final does not? What is the use case for such a combination?
回答1:
final does not require the function to override anything in the first place. Its effect is defined in [class.virtual]/4 as
If a virtual function
fin some classBis marked with the virt-specifierfinaland in a classDderived fromBa functionD::foverridesB::f, the program is ill-formed.
That's it. Now override final would simply mean
„This function overrides a base class one (override) and cannot be overriden itself (final).“final on it's own would impose a weaker requirement.
override and final have independent behavior.
Note that final can only be used for virtual functions though - [class.mem]/8
A virt-specifier-seq shall appear only in the declaration of a virtual member function (10.3).
Hence the declaration
void foo() final;
Is effectively the same as
virtual void foo() final override;
Since both require foo to override something - the second declaration by using override, and the first one by being valid if and only if foo is implicitly virtual, i.e. when foo is overriding a virtual function called foo in a base class, which makes foo in the derived one automatically virtual. Thus override would be superfluous in declarations where final, but not virtual, occurs.
Still, the latter declaration expresses the intent a lot clearer and should definitely be preferred.
回答2:
final does not necessarily imply that the function is overridden. It's perfectly valid (if of somewhat dubious value) to declare a virtual function as final on its first declaration in the inheritance hierarchy.
One reason I can think of to create a virtual and immediately final function is if you want to prevent a derived class from giving the same name & parameters a different meaning.
回答3:
(Skip to the end to see the conclusion if you're in a hurry.)
Both override and final can appear only in declaration in a virtual function. And both key words can be used in the same function declaration, but whether it is useful to use them both depends on situations.
Take the following code as an example:
#include <iostream>
using std::cout; using std::endl;
struct B {
virtual void f1() { cout << "B::f1() "; }
virtual void f2() { cout << "B::f2() "; }
virtual void f3() { cout << "B::f3() "; }
virtual void f6() final { cout << "B::f6() "; }
void f7() { cout << "B::f7() "; }
void f8() { cout << "B::f8() "; }
void f9() { cout << "B::f9() "; }
};
struct D : B {
void f1() override { cout << "D::f1() "; }
void f2() final { cout << "D::f2() "; }
void f3() override final { cout << "D::f3() "; } // need not have override
// should have override, otherwise add new virtual function
virtual void f4() final { cout << "D::f4() "; }
//virtual void f5() override final; // Error, no virtual function in base class
//void f6(); // Error, override a final virtual function
void f7() { cout << "D::f7() "; }
virtual void f8() { cout << "D::f8() "; }
//void f9() override; // Error, override a nonvirtual function
};
int main() {
B b; D d;
B *bp = &b, *bd = &d; D *dp = &d;
bp->f1(); bp->f2(); bp->f3(); bp->f6(); bp->f7(); bp->f8(); bp->f9(); cout << endl;
bd->f1(); bd->f2(); bd->f3(); bd->f6(); bd->f7(); bd->f8(); bd->f9(); cout << endl;
dp->f1(); dp->f2(); dp->f3(); dp->f6(); dp->f7(); dp->f8(); dp->f9(); cout << endl;
return 0;
}
The output is
B::f1() B::f2() B::f3() B::f6() B::f7() B::f8() B::f9()
D::f1() D::f2() D::f3() B::f6() B::f7() B::f8() B::f9()
D::f1() D::f2() D::f3() B::f6() D::f7() D::f8() B::f9()
Compare
f1()andf6(). We know thatoverrideandfinalis indepent sematically.overridemeans the function is overriding a virtual function in its base class. Seef1()andf3().finalmeans the function cannot be overrided by its derived class. (But the function itself need not override a base class virtual function.) Seef6()andf4().
Compare
f2()andf3(). We know that if a member function is declared withoutvirtualand withfinal, it means that it already override a virtual function in base class. In this case, the key wordoverrideis redundant.Compare
f4()andf5(). We know that if a member function is declared withvirtualand if it is not the first virtual function in inheritance hierarchy, then we should useoverrideto specify the override relationship. Otherwise, we may accidentally add new virtual function in derived class.Compare
f1()andf7(). We know that any member function, not just virtual ones, can be overridden in derived class. Whatvirtualspecifies is polymorphism, which means the decision as to which function to run is delayed until run time instead of compile time. (This should be avoid in practice.)Compare
f7()andf8(). We know that we can even override a base class function and make it a new virtual one. (Which means any member functionf8()of class derived fromDwill be virtual.) (This should be avoid in practice too.)Compare
f7()andf9(). We know thatoverridecan help us find the error when we want to override a virtual function in derived class while forgot to add key wordvirtualin base class.
In conclusion, the best practice in my own view is:
- only use
virtualin declaration of the first virtual function in base class; - always use
overrideto specify override virtual function in derived class, unlessfinalis also specified.
回答4:
No final does not necessarily imply override. In fact, you could declare a virtual function that you immediately declare final see here. The final keyword simply states that no derived class can create an override of this function.
The override keyword is important in that it enforces that you are indeed actually overriding a virtual function (instead of declaring a new unrelated one). See this post regarding override
So long story short, they each serve their own particular purpose, and it is often correct to use both.
回答5:
The following code (with the final specifier) compiles. But compilation fails when final is replaced with override final. Thus override final conveys more information (and prevents compilation) than just final.
class Base
{
public:
virtual ~Base() {}
};
class Derived : public Base
{
public:
virtual void foo() final
{
std::cout << "in Derived foo\n";
}
};
Essentially, override final says this method cannot be overridden in any derived class and this method overrides a virtual method in a base class. final alone doesn't specify the base class overriding part.
来源:https://stackoverflow.com/questions/29412412/does-final-imply-override