Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Modern C++ Programming Cookbook

You're reading from   Modern C++ Programming Cookbook Recipes to explore data structure, multithreading, and networking in C++17

Arrow left icon
Product type Paperback
Published in May 2017
Publisher Packt
ISBN-13 9781786465184
Length 590 pages
Edition 1st Edition
Languages
Tools
Arrow right icon
Author (1):
Arrow left icon
Marius Bancila Marius Bancila
Author Profile Icon Marius Bancila
Marius Bancila
Arrow right icon
View More author details
Toc

Table of Contents (13) Chapters Close

Preface 1. Learning Modern Core Language Features FREE CHAPTER 2. Working with Numbers and Strings 3. Exploring Functions 4. Preprocessor and Compilation 5. Standard Library Containers, Algorithms, and Iterators 6. General Purpose Utilities 7. Working with Files and Streams 8. Leveraging Threading and Concurrency 9. Robustness and Performance 10. Implementing Patterns and Idioms 11. Exploring Testing Frameworks 12. Bibliography

Using override and final for virtual methods

Unlike other similar programming languages, C++ does not have a specific syntax for declaring interfaces (that are basically classes with pure virtual methods only) and also has some deficiencies related to how virtual methods are declared. In C++, the virtual methods are introduced with the virtual keyword. However, the keyword virtual is optional for declaring overrides in derived classes that can lead to confusion when dealing with large classes or hierarchies. You may need to navigate throughout the hierarchy up to the base to figure out whether a function is virtual or not. On the other hand, sometimes, it is useful to make sure that a virtual function or even a derived class can no longer be overridden or derived further. In this recipe, we will see how to use C++11 special identifiers override and final to declare virtual functions or classes.

Getting ready

You should be familiar with inheritance and polymorphism in C++ and concepts, such as abstract classes, pure specifiers, virtual, and overridden methods.

How to do it...

To ensure correct declaration of virtual methods both in base and derived classes, but also increase readability, do the following:

  • Always use the virtual keyword when declaring virtual functions in derived classes that are supposed to override virtual functions from a base class, and
  • Always use the override special identifier after the declarator part of a virtual function declaration or definition.
        class Base 
{
virtual void foo() = 0;
virtual void bar() {}
virtual void foobar() = 0;
};

void Base::foobar() {}

class Derived1 : public Base
{
virtual void foo() override = 0;
virtual void bar() override {}
virtual void foobar() override {}
};

class Derived2 : public Derived1
{
virtual void foo() override {}
};
The declarator is the part of the type of a function that excludes the return type.

To ensure that functions cannot be overridden further or classes cannot be derived any more, use the final special identifier:

  • After the declarator part of a virtual function declaration or definition to prevent further overrides in a derived class:
        class Derived2 : public Derived1 
{
virtual void foo() final {}
};
  • After the name of a class in the declaration of the class to prevent further derivations of the class:
        class Derived4 final : public Derived1 
{
virtual void foo() override {}
};

How it works...

The way override works is very simple; in a virtual function declaration or definition, it ensures that the function is actually overriding a base class function, otherwise, the compiler will trigger an error.

It should be noted that both override and final keywords are special identifiers having a meaning only in a member function declaration or definition. They are not reserved keywords and can still be used elsewhere in a program as user-defined identifiers.

Using the override special identifier helps the compiler to detect situations when a virtual method does not override another one like shown in the following example:

    class Base 
{
public:
virtual void foo() {}
virtual void bar() {}
};

class Derived1 : public Base
{
public:
void foo() override {}
// for readability use the virtual keyword

virtual void bar(char const c) override {}
// error, no Base::bar(char const)
};

The other special identifier, final, is used in a member function declaration or definition to indicate that the function is virtual and cannot be overridden in a derived class. If a derived class attempts to override the virtual function, the compiler triggers an error:

    class Derived2 : public Derived1 
{
virtual void foo() final {}
};

class Derived3 : public Derived2
{
virtual void foo() override {} // error
};

The final specifier can also be used in a class declaration to indicate that it cannot be derived:

    class Derived4 final : public Derived1 
{
virtual void foo() override {}
};

class Derived5 : public Derived4 // error
{
};

Since both override and final have this special meaning when used in the defined context and are not in fact reserved keywords, you can still use them anywhere elsewhere in the C++ code. This ensured that existing code written before C++11 did not break because of the use of these names for identifiers:

    class foo 
{
int final = 0;
void override() {}
};
You have been reading a chapter from
Modern C++ Programming Cookbook
Published in: May 2017
Publisher: Packt
ISBN-13: 9781786465184
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image