Overriding virtual methods

Overriding virtual functions is one of the most important mechanisms of C++ object oriented programming. The derived class method is overriding base class method when following requirements are met:

  1. the base class method has virtual keyword,
  2. derived class method has:
    • the same name,
    • the same input parameters,
    • the same const-ness,
    • compatible return type.

If at least one of these requirement is not fulfilled, developer can end with not-overriding method and not even know about it. The C++11 standard introduces specifier override, designed for easy detection of such mistakes.

The simply idea of overriding is that the following code should call print function from Derived class:

class Base
{
public:
    virtual void print(int value);
};

class Derived : public Base
{
public:
    void print(int value);
};

Base* bPointer = new Derived();
bPointer->print(5);

This code definitely will work in the intended way, but let’s take a look on a different variations of print method in Derived class. Which one of them – 1, 2 or 3 – will override the print from Base class?

class Derived : public Base
{
public:
// virtual void print(int value) const;    // 1
// virtual bool print(int value);          // 2
// virtual void print(unsigned int value); // 3
};

The answer is: none of them!

None of these declarations will allow the method print to be overridden (1 - constness, 2 - inconsistent return type, 3 – inconsistent parameter type). The same thing is if we forget to make print virtual in the Base class. All of these mistakes are easy to do but hard to catch. There are big chances that you will not get any warnings for such implementation. It’s not incorrect – but it probably will not behave the way you wanted.

And here comes C++11 with the new override specifier!

Override in C++11

Just declare methods in Derived class override and the compiler will check for you if there is everything ok with your overriding plans.

class Derived : public Base
{
public:
void print(int value) const override; //error!
};

You will get here compilation error since print is non-const in Base class.

This is how usage of override specifier provides you more safety and allows you to spot bugs early.

Override equivalent for Qt

Qt is not lagging behind C++ standard. Since Qt5 there is available macro Q_DECL_OVERRIDE which is equal to override from C++11.

Usage is also analogous, example:

void print(int value) const Q_DECL_OVERRIDE;

Final specifier

Besides of override specifier, C++11 introduces also another specifier helpful for working with inheritance: final specifier. This one can be included to function declaration or a class definition when you want to make sure that this method will not be overriden or the class will not be used as a base class.

Usage of final method

Usage is very simple. Just add the specifier final after method declaration.

class Base
{
    virtual void method() final;
};

class Derived : public Base
{
    void method(); // error!
};

Compiler will report an error, because it’s illegal to override final functions.

When to use it?

The introduction of final method into C++11 raises some questions. If somebody doesn’t want to allow to override one function, why did he make it virtual? Wouldn’t be better just to remove virtual keyword from the function in the most base class?

The answer is: no, because it’s not always possible.

Imagine that you own a base class with some virtual methods you want to override. You do so in class Derived; and from this point, the method should not be overriden in any other class. With final specifier you can prevent the method from overriding starting with any class in hierarchy. It is shown in following example:

class Base
{
    virtual void method();
};

class Derived : public Base
{
    void method() final;
};

class SecondDerived : public Derived
{
    void method(); // error!
};

The mechanism can be also used by optimization. Calling a virtual function is slower than calling not-virtual function. You can use final method to achieve devirtualization - if you call virtual method from the static object that defined this method as final, the compiler can devirtualize the call and the call has performance of not-virtual method call.

Usage of final class

When a class is not designed to be a base class, add final specifier after its name. The compilation will fail if somebody will try to inherit such class.

class NotBase final
{
};

class Derived : public NotBase // error!
{
};

When it’s useful?

Some classes are not intended to be inherited from, like std::vector or std::list, classes without virtual destructor or platform dependent classes.

Final specifier is designed for quite specific scenarios. For sure you will not see it very often in the code - the usage is just very particular, in opposite to his sibling override, which should be used wherever possible.

Further reading