C++. Restrictions on virtual functions. The final specifier

Restrictions on virtual functions. The final specifier

This topic is a continuation of the topic:


Contents


Search other resources:

1. Restrictions on virtual functions

The following general restrictions apply to virtual functions:

  • virtual functions should be used only in classes that form an inheritance hierarchy;
  • virtual functions cannot be used as ordinary functions that are not taken in a class wrapper;
  • global functions cannot be virtual;
  • virtual functions in a class cannot be declared static using the static keyword.

 

2. Restrictions on the use of virtual functions. The final specifier

In C++, you can restrict the injection of virtual functions into class hierarchies. If it is necessary to prohibit the use of the name of a virtual function in inherited classes, then the final specifier is used for this. If functions in the class hierarchy are declared as non-virtual (without the virtual specifier), attempting to use the final specifier will result in a compilation error.

A virtual function declaration with the final specifier can be considered in the context of two applications:

  • when a function is declared with the virtual keyword. The syntax of the C++ language allows you to declare a virtual function and, at the same time, prohibits the use of the name of this function in inherited classes;
  • when a function is declared with the override keyword. This is the case when a function overrides a base class function of the same name. The syntax allows redefining the base class function of the same name without the override keyword.

In the case of declaring a function with the virtual keyword in a class, the general form of such a function is as follows

virtual return_type FuncName(parameters) final
{
  // ...
}

here

  • FuncName – the name of a virtual function that is not allowed to be used in inherited classes;
  • parameters – function parameters;
  • return_type – type of return from the function.

If in some class a virtual function is declared with the override modifier, then to prohibit the use of the name of this function in inherited classes, the following form is used

return_type FuncName(parameters) override final
{
  // ...
}

or without using the override keyword

return_type FuncName(parameters) final
{
  // ...
}

 

3. An example of using a restriction on a function declared with the virtual specifier

Below is an example of two classes A and B that form an inheritance hierarchy. Class A is the base class, class B is derived (inherited).

Class A declares a virtual function Print() with the virtual keyword. At the same time, that function is declared as final. Such a declaration would cause all derived classes to be prohibited from using the Print() name.

// Base class
class A
{
public:
  // Here a virtual function is declared with the final specifier
  virtual void Print() final
  {
    cout << "A.Print()" << endl;
  }
};

// Derived (inherited) class
class B :A
{
public:
  // It is forbidden to override a virtual function,
  // which is declared with the final specifier
  void Print() // Compilation error occurs here
  {
    cout << "B.Print()" << endl;
  }
};

 

4. An example of applying a constraint on a virtual function declared with the override specifier

The example declares three classes named A, B, C, which form a hierarchy. Class A is placed at the top of the hierarchy. Class A declares a virtual function with the virtual keyword, the first in the chain of virtual functions.

Class B declares a virtual function with the override keyword, which continues the chain of virtual functions. This function is declared with the final specifier. This means that it is forbidden to use the name of a virtual function in an inherited class C.

#include <iostream>
using namespace std;

// Base class
class A
{
public:
  // Virtual function declaration
  virtual void Print()
  {
    cout << "A::Print()" << endl;
  }
};

// Inherited class
class B :A
{
public:
  // This is where a virtual function is declared,
  // which restricts the use of the name Print() in inherited classes
  void Print() override final
  {
    cout << "B::Print()" << endl;
  }
};

// Inherited class
class C :B
{
public:
  // It is forbidden to override a final function B::Print()
  void Print() override // compilation error
  {
    cout << "C::Print()" << endl;
  }
};

 


Related topics