So we have a class in our C++-98 code base that looks like that:
struct abstract_concrete_base { virtual ∼abstract_concrete_base(); virtual void consume(); };
Down the hierarchy we have some class that overrides the consume() function3:
struct serious_business : abstract_concrete_base { void consume(); };
Suddenly, the base class has some work to do in consume() regardless of the details of the derived classes. Also, it is well known that one should prefer non-virtual public functions calling virtual private functions, so let’s update our code:
struct abstract_concrete_base { virtual ∼abstract_concrete_base(); void consume() { stuff_from_base_class(); do_consume(); } private: void stuff_from_base_class(); virtual void do_consume(); };
Nice. Everything compiles well but all derived classes are broken. It turns out that since do_consume() is not a pure virtual function, there is no problem to instantiate the class. All derived will use the default do_consume() and their old consume() is now just another function of theirs.
Wouldn’t it be nice if there was a way to detect the problem?
That’s why the override keyword has been introduced in C++11. By modifying the initial implementation of serious_business as follows:
struct serious_business : abstract_concrete_base { void consume() override; };
The programmer explicitly tells the compiler that this function is expected to override the same function from a parent class. So when abstract_concrete_base is updated and its consume() function becomes non-virtual, the compiler will immediately complain that the function from serious_business does not override anything. Good!
Another keyword related to inheritance and function overriding has been introduced in C++11: the final keyword. When used in place of override, it tells the compiler that the function should not be overridden in the derived classes. Previously a virtual function could be overridden anywhere from the top to the bottom of the hierarchy. Now if one declaration is marked as final, the derived classes are not allowed to redefine the function anymore.
Additionally, one can place the final keyword after the name of a class to indicate that this class cannot be derived at all:
struct serious_business final : abstract_concrete_base
{
void consume() override;
};
3You may also find versions of this pattern in the wild where the virtual keyword is repeated in the derived classes, so the reader can suppose that it is an overridden function without looking at the declaration of the parent class.