C++. Обмеження віртуальних функцій. Специфікатор final

Обмеження віртуальних функцій. Специфікатор final

Дана тема є продовженням наступної теми:


Зміст


Пошук на інших ресурсах:

1. Обмеження віртуальних функцій

На віртуальні функції накладаються наступні загальні обмеження:

  • віртуальні функції потрібно використовувати тільки в класах, які утворюють ієрархію спадковості;
  • віртуальні функції не можуть застосовуватись як звичайні функції, що не взяті в оболонку класу;
  • глобальні функції не можуть бути віртуальними;
  • віртуальні функції у класі не можуть бути оголошені як статичні з використанням ключового слова static.

 

2. Обмеження на використання віртуальних функцій. Специфікатор final

У мові C++ можна обмежити використання віртуальних функцій в ієрархії класів. Якщо потрібно заборонити використання імені віртуальної функції в успадкованих класах, то для цього використовується специфікатор final. Якщо функції в ієрархії класів оголошуються як невіртуальні (без специфікатора virtual), то спроба використати специфікатор final призведе до помилки компіляції.

Оголошення віртуальної функції зі специфікатором final може бути розглянуто в контексті двох застосувань:

  • коли функція оголошується з ключовим словом virtual. Синтаксис мови C++ дозволяє оголосити функцію, яка є віртуальною, і, в той же час, забороняє використання імені цієї функції в успадкованих класах;
  • коли функція оголошується з ключовим словом override. Це випадок, коли функція перевизначає однойменну функцію базового класу. Синтаксисом допускається перевизначення однойменної функції базового класу без ключового слова override.

У випадку оголошення функції з ключовим словом virtual в класі, загальний вигляд такої функції наступний

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

тут

  • FuncName – ім’я віртуальної функції, яке забороняється використовувати в успадкованих класах;
  • parameters – параметри функції;
  • return_type – тип повернення з функції.

Якщо в деякому класі віртуальна функція оголошується з модифікатором override, то щоб заборонити використання імені цієї функції в успадкованих класах, використовується наступна форма

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

або без використання ключового слова override

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

 

3. Приклад використання обмеження на функцію, яка оголошена зі специфікатором virtual

Нижче наведено приклад двох класів A та B, які утворюють ієрархію успадкування. Клас A є базовий клас, клас B є похідний (успадкований).
У класі A оголошується віртуальна функція Print() з ключовим словом virtual. У той же час, ця функція оголошується як final. Таке оголошення призведе до того, що в усіх успадкованих класах буде заборонено використовувати ім’я Print().

// Базовий клас
class A
{
public:
  // Тут оголошується віртуальна функція зі специфікатором final
  virtual void Print() final
  {
    cout << "A.Print()" << endl;
  }
};

// Похідний (успадкований) клас
class B :A
{
public:
  // Заборонено перевизначати віртуальну функцію,
  // яка оголошена з специфікатором final
  void Print() // Тут помилка компіляції
  {
    cout << "B.Print()" << endl;
  }
};

 

4. Приклад застосування обмеження на віртуальну функцію, яка оголошена зі специфікатором override

У прикладі оголошується три класи з іменами A, B, C які утворюють ієрархію.
Клас A розміщується в вершині ієрархії. У класі A оголошується віртуальна функція з ключовим словом virtual, яка є першою в ланцюжку віртуальних функцій.
У класі B оголошується віртуальна функція з ключовим словом override, яка продовжує ланцюжок віртуальних функцій. Ця функція оголошуєтьяс з специфікатором final. Це означає, що в успадкованому класі C заборонено використовувати ім’я даної віртуальної функції.

#include <iostream>
using namespace std;

// Базовий клас
class A
{
public:
  // Тут оголошується віртуальна функція
  virtual void Print()
  {
    cout << "A::Print()" << endl;
  }
};

// Похідний (успадкований) клас
class B :A
{
public:
  // Тут оголошується віртуальна функція,
  // яка обмежує використання імені Print() в успадкованих класах
  void Print() override final
  {
    cout << "B::Print()" << endl;
  }
};

// Похідний клас
class C :B
{
public:
  // Заборонено перевизначати final-функцію B::Print()
  void Print() override // помилка компіляції
  {
    cout << "C::Print()" << endl;
  }
};

 


Споріднені теми