What's the point of a final virtual function?

Viewed 24187

Wikipedia has the following example on the C++11 final modifier:

struct Base2 {
    virtual void f() final;
};

struct Derived2 : Base2 {
    void f(); // ill-formed because the virtual function Base2::f has been marked final
};

I 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?

10 Answers

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.

Instead of this:

public:
    virtual void f();

I find it useful to write this:

public:
    virtual void f() final
        {
        do_f(); // breakpoint here
        }
protected:
    virtual void do_f();

The main reason being that you now have a single place to breakpoint before dispatching into any of potentially many overridden implementations. Sadly (IMHO), saying "final" also requires that you say "virtual."

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.

Related