Does final imply override?
Solution 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
f
in some classB
is marked with the virt-specifierfinal
and in a classD
derived fromB
a functionD::f
overridesB::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.
Solution 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.
Solution 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 thatoverride
andfinal
is indepent sematically.override
means the function is overriding a virtual function in its base class. Seef1()
andf3()
.final
means 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 withoutvirtual
and withfinal
, it means that it already override a virtual function in base class. In this case, the key wordoverride
is redundant.Compare
f4()
andf5()
. We know that if a member function is declared withvirtual
and if it is not the first virtual function in inheritance hierarchy, then we should useoverride
to 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. Whatvirtual
specifies 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 fromD
will be virtual.) (This should be avoid in practice too.)Compare
f7()
andf9()
. We know thatoverride
can help us find the error when we want to override a virtual function in derived class while forgot to add key wordvirtual
in base class.
In conclusion, the best practice in my own view is:
- only use
virtual
in declaration of the first virtual function in base class; - always use
override
to specify override virtual function in derived class, unlessfinal
is also specified.
Solution 4
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.
Solution 5
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.
![quant](https://i.stack.imgur.com/lAhj3.png?s=256&g=1)
quant
I'm here to learn programming and *nix mostly, and am immensely indebted to this community for always being there when I get stuck. The help and support I've received on SE sites has allowed me to develop my understanding in a range of disciplines much faster than I could ever have hoped for. I try to give back once in a while as well; it's the least I could do. I'm the owner and maintainer of www.portnovel.com
Updated on October 06, 2020Comments
-
quant over 3 years
As I understand it, the
override
keyword states that a given declaration implements a basevirtual
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 thisvirtual
function.So is
override final
redundant? It seems to compile fine. What information doesoverride final
convey thatfinal
does not? What is the use case for such a combination? -
Carlton about 9 years+1 For showing a feasible use-case of a virtual/immediately-final function. I wonder if the compiler still generates a vtable when this is done though?
-
Angew is no longer proud of SO about 9 years@Carlton That's up to the compiler. As far as the standard is concerned, it makes the class polymorphic, however - which means
dynamic_cast
must work for it, for example. I believe vtable implementations of virtual functions also need the vtable to makedynamic_cast
work. -
Carlton about 9 yearsBahh, I just posted a question based on my previous comment, but you pretty much just answered it here. Thanks.
-
Markus Mayr about 9 yearsI like your answer, but I'd like to clarify that from a practical point of view
virtual void f() final override
andvoid f() final
are equivalent in the sense that both of them fail if they do not override something.final
is only valid for virtual functions and the latter declaration off
is only virtual if it overrides a function. Error messages for the latter one may be less precise though. -
antred about 9 yearsHmm, I wish that first example you posted wouldn't compile, because the way I see it declaring a virtual function and making it final in the same breath makes absolutely no sense at all.
-
Johan Lundberg over 8 years"final alone doesn't specify the base class overriding part." Correct, but
void foo() final
does. -
Wolf over 6 yearsIf you want to prevent a derived class from giving the same name & parameters a different meaning, don't make it a virtual method. I don't see a feasible use-case in this vague description (unlike @Carlton), but I am really interested in one.
-
Angew is no longer proud of SO over 6 years@Wolf I meant same non-qualified name, of course. Comments can't show code well, but I've written an example offsite.
Derived2
cannot hidemustRemainBase
. -
Wolf over 6 yearsthe latter declaration expresses the intent a lot clearer - I don't think so. Your description has led me to prefer the first declaration style for the same reason I'd avoid to add
virtual
when overriding a virtual method: it adds no value. But it's of course better than writingvirtual void foo() final;
-
Columbo over 6 years@Wolf You don't think it expresses the intent clearer? Could you articulate exactly what the intent is that is expressed by the first declaration form?
-
Wolf over 6 yearsThanks for doing the extra work, but I'm still not able to get the point. The relation between
Derived1
andBase1
I'd consider bad style, because overriding (hiding) is not really helpful for non-virtual methods. I'm looking on Columbo`s and your answer as to understand if a combination of virtual+final+override is really useful or just a waist of time. -
Wolf over 6 yearsI think
final
has to bevirtual
after your description (I'm just learning these new features) and since you omit thevirtual
keyword, it wouldn't compile if it was not anoverride
. Or maybe I am overlooking a case that could lead to unwanted behaviour? The use of non-overriding final virtual I'm just trying to figure out below Angew's answer ... -
Wolf over 6 yearsI should add that bot variants you list in your answer are clear concerning their intent, only
virtual void foo() final;
would be unclear. -
Columbo over 6 years@Wolf If I regard the first line lexically, all I can immediately discern is that it cannot be overriden. The fact that
final
implies the function must be virtual to begin with is language-specific and not even that well-known, so the first line doesn't express its intent in a manner equally comprehensible and language-agnostic as the second one's. -
Wolf over 6 yearsI have to admit that I have to get used to it first. Just one note, wouldn't it be better to suggest writing
void foo() final override;
to show intent clearly without introducing redundancies? -
Columbo over 6 years@Wolf IMO the
virtual
keyword is not redundant at all. According to your argument,override
is just as redundant, and you seem to concede that it is not, at least not in the context of expressiveness. -
Angew is no longer proud of SO over 6 years@Wolf I wouldn't call hiding bad style, it has very legitimate use cases, particularly in combination with template techniques.
-
Chris Guzak over 6 yearscpp core guidelines say only use one github.com/isocpp/CppCoreGuidelines/blob/master/…
-
Sonic78 almost 6 yearsMost likely that is the reason why e. g. the Google C++ Style Guide suggests to "annotate overrides of virtual functions or virtual destructors with exactly one of an override or (less frequently) final specifier. Do not use virtual when declaring an override".
-
goji over 5 yearsClang-tidy has a check (modernize-use-override) that complains when you use both override and final.
-
Dolphin over 3 yearsin the case where there is no base class method, the couple compilers I tried
void f() final
complains the function is not virtual, whereasvoid f() final override
complains that there is not a method being overridden (and sometimes that the method is not virtual).override
is most commonly used to catch errors with base class methods changing. In this case, we would want the error that comes withfinal override
as a dev unfamiliar with the code might 'fix' the error by adding virtual to the method, instead of updating the method to match the signature in the base class. -
Hedede over 2 yearsHowever, it still doesn't prevent a derived class from hiding a final virtual by adding an extra parameter. I.e. a derived class can declare
void mustRemainBase(int = 0);
and hide the original.