Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about CollectivesTeams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams struct Derived2 : Base2 { void f(); // ill-formed because the virtual function Base2::f has been marked finalI don't understand the point of introducing a virtual function and immediately marking it as final. Is this simply a bad example, or is there more to it?
You can always use it to confuse people by using the keyword as an identifier:
int final = 7;
If you want Stroustrup's talk on it, though,
see here
.
–
chris
Jul 28, 2012 at 20:33
What part of "It's an example" is difficult to understand? Most of the other pieces of example code are similarly pointless. The purpose of an example is to show how the functionality works.
–
Nicol Bolas
Jul 28, 2012 at 21:34
Typically
final
will not be used on the base class' definition of a virtual function.
final
will be used by a derived class that overrides the function in order to prevent further derived types from further overriding the function. Since the overriding function must be virtual normally it would mean that anyone could override that function in a further derived type.
final
allows one to specify a function which overrides another but which cannot be overridden itself.
For example if you're designing a class hierarchy and need to override a function, but you do not want to allow users of the class hierarchy to do the same, then you might mark the functions as final in your derived classes.
Since it's been brought up twice in the comments I want to add:
One reason some give for a base class to declare a non-overriding method to be final is simply so that anyone trying to define that method in a derived class gets an error instead of silently creating a method that 'hides' the base class's method.
struct Base {
void test() { std::cout << "Base::test()\n"; }
void run(Base *o) {
o->test();
// Some other developer derives a class
struct Derived : Base {
void test() { std::cout << "Derived::test()\n"; }
int main() {
Derived o;
o.test();
run(&o);
Base
's developer doesn't want Derived
's developer to do this, and would like it to produce an error. So they write:
struct Base {
virtual void test() final { ... }
Using this declaration of Base::foo()
causes the definition of Derived to produce an error like:
<source>:14:13: error: declaration of 'test' overrides a 'final' function
void test() { std::cout << "Derived::test()\n"; }
<source>:4:22: note: overridden virtual function is here
virtual void test() final { std::cout << "Base::test()\n"; }
You can decide if this purpose is worthwhile for yourself, but I want to point out that declaring the function virtual final
is not a full solution for preventing this kind of hiding. A derived class can still hide Base::test()
without provoking the desired compiler error:
struct Derived : Base {
void test(int = 0) { std::cout << "Derived::test()\n"; }
Whether Base::test()
is virtual final
or not, this definition of Derived
is valid and the code Derived o; o.test(); run(&o);
behaves exactly the same.
As for clear statements to users, personally I think just not marking a method virtual
makes a clearer statement to users that the method is not intended to be overridden than marking it virtual final
. But I suppose which way is clearer depends on the developer reading the code and what conventions they are familiar with.
I don't see any reason why not, but I also don't see any strong reason to do it since you can already mark functions final override
. Perhaps there should be a style warning that requires all final
functions to also be marked override
like the other virtual
and override
style warnings.
– bames53
Jul 29, 2012 at 1:29
Well final methods in interfaces would be an example of a final method in a "base" class. Also 'final' yields an error or at least a warning if somebody defines a function with the same name in a subclass. The question is if compilers immediately devirtualize such a case.
– Trass3r
Mar 11, 2013 at 13:58
@Trass3r It would not be possible to implement a final
interface method, because implementing an interface method in C++ requires overriding. Such an unimplementable interface would not be useful.
– bames53
Mar 11, 2013 at 21:19
If a virtual function f in some class B is marked with the virt-specifier final and in a class D derived from
B a function D::f overrides B::f, the program is ill-formed. [...]
i.e., final
is required to be used with virtual functions (or with classes to block inheritance) only. Thus, the example requires virtual
to be used for it to be valid C++ code.
EDIT: To be totally clear: The "point" asked about concerns why virtual is even used. The bottom-line reason why it is used is (i) because the code would not otherwise compile, and, (ii) why make the example more complicated using more classes when one suffices? Thus exactly one class with a virtual final function is used as an example.
Respectfully, I totally get the point of the question. The "point" asked about concerns why virtual is even used. The bottom-line reason why it is used is because the code would not otherwise compile AND why make the example more complicated using more classes when one suffices? Thus exactly one class with a virtual final function is used to as an example. QED.
– Paul Preney
Jul 29, 2012 at 2:00
@Luchian Grigore: I added an edit to be completely clear since I did not wrap up my answer with the "bottom-line reason". Perhaps why this question is getting so many comments is due to everyone naturally looking at the example and saying, "Why would anyone use that code?" and not looking at it from the example writer's point-of-view. Most examples are written to be practically useful --this one is not except to make a minimal example showing how it behaves.
– Paul Preney
Jul 29, 2012 at 2:30
It doesn't seem useful at all to me. I think this was just an example to demonstrate the syntax.
One possible use is if you don't want f to really be overrideable, but you still want to generate a vtable, but that is still a horrible way to do things.
Final and virtual are two different aspects. It becomes relevant in the override versus overload context. A virtual qualifier implies Run Time Type Inference. A non-virtual implies compile type type inference. When there is overloading involved, and type promotion/conversion involved a non-virtual type can lead to interesting results. Typically though you are encouraged not to write that kind of code.
– VSOverFlow
Jul 29, 2012 at 23:55
@sasha.sochka I think for example that dynamic_cast
won't work without one. But the usual way to ensure a vtable is to make the destructor virtual.
– Mark Ransom
May 5, 2014 at 1:32
Adding to the nice answers above - Here is a well-known application of final (very much inspired from Java). Assume we define a function wait() in a Base class, and we want only one implementation of wait() in all its descendants. In this case, we can declare wait() as final.
For example:
class Base {
public:
virtual void wait() final { cout << "I m inside Base::wait()" << endl; }
void wait_non_final() { cout << "I m inside Base::wait_non_final()" << endl; }
and here is the definition of the derived class:
class Derived : public Base {
public:
// assume programmer had no idea there is a function Base::wait()
// error: wait is final
void wait() { cout << "I am inside Derived::wait() \n"; }
// that's ok
void wait_non_final() { cout << "I am inside Derived::wait_non_final(); }
It would be useless (and not correct) if wait() was a pure virtual function. In this case: the compiler will ask you to define wait() inside the derived class. If you do so, it will give you an error because wait() is final.
Why should a final function be virtual? (which is also confusing) Because (imo) 1) the concept of final is very close to the concept of virtual functions [virtual functions has many implementations - final functions has only one implementation], 2) it is easy to implement the final effect using vtables.
This answer actually explains everything instead of simply stating that "otherwise it would be wrong" or "because it is an example", imho this should be accepted as the answer to this question.
– Troyseph
Feb 18, 2015 at 9:44
I don't understand the point of introducing a virtual function and immediately marking it as final.
The purpose of that example is to illustrate how final
works, and it does just that.
A practical purpose might be to see how a vtable influences a class' size.
struct Base2 {
virtual void f() final;
struct Base1 {
assert(sizeof(Base2) != sizeof(Base1)); //probably
Base2
can simply be used to test platform specifics, and there's no point in overriding f()
since it's there just for testing purposes, so it's marked final
. Of course, if you're doing this, there's something wrong in the design. I personally wouldn't create a class with a virtual
function just to check the size of the vfptr
.
While refactoring legacy code (e.g. removing a method that is virtual from a mother class), this is useful to ensure none of the child classes are using this virtual function.
// Removing foo method is not impacting any child class => this compiles
struct NoImpact { virtual void foo() final {} };
struct OK : NoImpact {};
// Removing foo method is impacting a child class => NOK class does not compile
struct ImpactChildClass { virtual void foo() final {} };
struct NOK : ImpactChildClass { void foo() {} };
int main() {}
Here is why you might actually choose to declare a function both virtual
and final
in a base class:
class A {
void f();
class B : public A {
void f(); // Compiles fine!
class C {
virtual void f() final;
class D : public C {
void f(); // Generates error.
A function marked final
has to be also be virtual
. Marking a function final
prevents you from declaring a function with the same name and signature in a derived class.
I found another case where for virtual function is useful to be declared as final. This case is part of SonarQube list of warnings. The warning description says:
Calling an overridable member function from a constructor or destructor could result in unexpected behavior when instantiating a subclass which overrides the member function.
For example:
- By contract, the subclass class constructor starts by calling the parent class constructor.
- The parent class constructor calls the parent member function and not the one overridden in the child class, which is confusing for child class' developer.
- It can produce an undefined behavior if the member function is pure virtual in the parent class.
Noncompliant Code Example
class Parent {
public:
Parent() {
method1();
method2(); // Noncompliant; confusing because Parent::method2() will always been called even if the method is overridden
virtual ~Parent() {
method3(); // Noncompliant; undefined behavior (ex: throws a "pure virtual method called" exception)
protected:
void method1() { /*...*/ }
virtual void method2() { /*...*/ }
virtual void method3() = 0; // pure virtual
class Child : public Parent {
public:
Child() { // leads to a call to Parent::method2(), not Child::method2()
virtual ~Child() {
method3(); // Noncompliant; Child::method3() will always be called even if a child class overrides method3
protected:
void method2() override { /*...*/ }
void method3() override { /*...*/ }
Compliant Solution
class Parent {
public:
Parent() {
method1();
Parent::method2(); // acceptable but poor design
virtual ~Parent() {
// call to pure virtual function removed
protected:
void method1() { /*...*/ }
virtual void method2() { /*...*/ }
virtual void method3() = 0;
class Child : public Parent {
public:
Child() {
virtual ~Child() {
method3(); // method3() is now final so this is okay
protected:
void method2() override { /*...*/ }
void method3() final { /*...*/ } // this virtual function is "final"
virtual
+ final
are used in one function declaration for making the example short.
Regarding the syntax of virtual
and final
, the Wikipedia example would be more expressive by introducing struct Base2 : Base1
with Base1 containing virtual void f();
and Base2 containing void f() final;
(see below).
Standard
Referring to N3690:
virtual
as function-specifier
can be part of decl-specifier-seq
final
can be part of virt-specifier-seq
There is no rule having to use the keyword virtual
and the Identifiers with special meaning final
together. Sec 8.4, function definitions (heed opt = optional):
function-definition:
attribute-specifier-seq(opt) decl-specifier-seq(opt) declarator virt-specifier-seq(opt) function-body
Practice
With C++11, you can omit the virtual
keyword when using final
. This compiles on gcc >4.7.1, on clang >3.0 with C++11, on msvc, ... (see compiler explorer).
struct A
virtual void f() {}
struct B : A
void f() final {}
int main()
auto b = B();
b.f();
PS: The example on cppreference also does not use virtual together with final in the same declaration.
PPS: The same applies for override
.
I think most of the answers miss an important point. final
means no more override
after it has been specified. Marking it on a base class is close to pointless indeed.
When a derived class might get derived further, it can use final
to lock the implementation of a given method to the one it provided.
#include <iostream>
class A {
public:
virtual void foo() = 0;
virtual void bar() = 0;
class B : public A {
public:
void foo() final override { std::cout<<"B::foo()"<<std::endl; }
void bar() override { std::cout<<"B::bar()"<<std::endl; }
class C : public B {
public:
// can't do this as B marked ::foo final!
// void foo() override { std::cout<<"C::foo()"<<std::endl; }
void bar() override { std::cout<<"C::bar()"<<std::endl; }
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.