Final Specifier in C++



The final specifier was introduced in C++11 with two main purposes −

  • The first purpose is to prevent inheritance. When a class is marked with final, other classes can not inherit from it.
  • The second purpose it to avoid function overriding. When you mark a virtual function with final, then it can not be overridden in the derived classes.

Read this chapter to learn how to use the final specifier in C++.

Using the final Specifier with Class

You can mark a class as final to prevent inheritance. After marking a class as final, you can no longer use this class for inheritance. Other classes will not be able to inherit them.

The syntax for using final specifier with a class is given below −

class MyClass final {
   // class members
};

Example

Here is an example demonstrating the difference between a class when used with final and when used without final −

In this example, we are using the final specifier with Base class and the Derived class is inheriting the base class. It will give an error in output as shown below −

#include <iostream>
using namespace std;

class Base final // final class
{
   public:
   void display(){
      cout << "Base class" << endl;
   }
};

// Inheriting from final class
class Derived : public Base {
   public:
   void show(){
      cout << "Derived class" << endl;
   }
};

int main() {
   Base b;
   b.display();
   return 0;
}

The output of the above code is given below −

main.cpp:14:7: error: cannot derive from 'final' base 'Base' in derived 
type 'Derived'
   14 | class Derived : public Base
      |       ^~~~~~~

In this example, we have removed the final specifier from Base class and the Derived class is inheriting the base class. It will not give any error and will work normally −

#include <iostream>
using namespace std;

class Base  // removed final 
{
   public:
   void display(){
      cout << "Base class called" << endl;
   }
};

// Inheriting from non-final class
class Derived : public Base {
   public:
   void show(){
      cout << "Derived class called" << endl;
   }
};

int main(){
   Base b;
   b.display();
   return 0;
}

The output of the above code is as follows −

Base class called

Using the final Specifier with Function

You can mark a function with final to avoid overriding the function. After marking a function as final, you can no longer override that function. The function can only be made final if the function is a virtual function.

The syntax to use final specifier with a function is given below −

class Base {
   public:
   virtual void display() final {
      // implementation
   }
};

Example

The example below demonstrates the difference between a function when used with final and when used without final −

In this example, we have used final specifier on the virtual function breathe() in Mammal class. In the Dog class, we are trying to override the breathe() function which will give an error in the output.

#include <iostream>
using namespace std;

class Animal {
   public:
   virtual void makeSound(){
      cout << "Animal sound" << endl;
   }

   virtual void breathe(){
      cout << "Animal breathing" << endl;
   }
};

class Mammal : public Animal {
   public:
   void makeSound() override{
      cout << "Mammal sound" << endl;
   }

   // final function
   void breathe() final override {
      cout << "Mammal breathing" << endl;
   }
};

class Dog : public Mammal{
   public:
   void makeSound() override {
      cout << "Bark" << endl;
   }

   // This would cause an error
   void breathe() override { 
      cout << "Dog breathing" << endl;
   }
};

int main(){
   Dog dog;
   dog.makeSound(); 
   dog.breathe();   
   return 0;
}

The output of the above code is as follows −

main.cpp:42:10: error: virtual function 'virtual void Dog::breathe()' overriding 
final function
   42 |     void breathe() override
      |          ^~~~~~~
main.cpp:27:10: note: overridden function is 'virtual void Mammal::breathe()'
   27 |     void breathe() final override
      |          ^~~~~~~

In this example, we have removed the final specifier from breathe() function in Mammal class. After overriding the breathe() function in the Dog class it will work normally without any error printing the overridden value in the output.

#include <iostream>
using namespace std;

class Animal {
   public:
   virtual void makeSound(){
      cout << "Animal sound" << endl;
   }

   virtual void breathe(){
      cout << "Animal breathing" << endl;
   }
};

class Mammal : public Animal{
   public:
   void makeSound() override {
      cout << "Mammal sound" << endl;
   }

   // Removed final 
   void breathe() override {
      cout << "Mammal breathing" << endl;
   }
};

class Dog : public Mammal{
   public:
   void makeSound() override {
       cout << "Bark" << endl;
   }

   // This is safe now
   void breathe() override { 
      cout << "Dog breathing" << endl;
   }
};

int main(){
   Dog dog;
   dog.makeSound(); 
   dog.breathe();   
   return 0;
}

The output of the above code is as follows −

Bark
Dog breathing

Conclusion

The final specifier in C++ helps in preventing the inheritance of classes and the overriding of the virtual function. In this chapter, we explained in detail how the final specifier works with class and virtual function.

Advertisements