Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
+ООП_Навч_посібник.doc
Скачиваний:
7
Добавлен:
01.07.2025
Размер:
6.58 Mб
Скачать

16.2.2. Успадкування віртуальних функцій

Атрибут virtual передається "за успадкуванням".

Якщо функція оголошується як віртуальна, то вона залишається такою незалежно від того, через скільки рівнів похідних класів вона може пройти. Наприклад, якби клас secondD був виведений з класу firstD, а не з класу baseClass, як це показано в наведеному нижче прикладі, то функція who(), як і раніше, залишалася б віртуальною, і механізм вибору відповідної версії теж працював би коректно.

// Цей клас виведений з класу firstD, а не з baseClass.

class secondD : public firstD {

public:

// Перевизначення функції who() для класу secondD.

void who() { cout << "Другий похідний клас.\n";}

};

Якщо похідний клас не перевизначає віртуальну функцію, то використовується функція, яка була визначена в базовому класі. Наприклад, перевіримо, як поведеться версія попередньої програми, якщо у класі secondD не буде перевизначено функції who().

Код програми 16.3. Демонстрація механізму успадкування віртуальних функцій

#include <iostream> // Для потокового введення-виведення

using namespace std; // Використання стандартного простору імен

class baseClass { // Оголошення базового класу

public:

virtual void who() { cout << "Базовий клас.\n";}

};

// Клас firstD виведений з класу baseClass

class firstD : public baseClass {

public:

void who() { cout << "Перший похідний клас.\n";}

};

class secondD : public baseClass {

// Функція who() тут взагалі не визначена.

};

int main()

{

baseClass Base_ob; // Створення об'єкта базового типу

baseClass *p; // Створення покажчика на об'єкт базового типу

firstD First_ob; // Створення об'єкта похідного типу

secondD Second_ob; // Створення об'єкта похідного типу

p = &Base_ob; // Присвоєння адреси об'єкта базового класу

p->who(); // Доступ до функції who() класу baseClass

p = &First_ob; // Присвоєння адреси об'єкта похідного класу

p->who(); // Доступ до функції who() класу firstD

p = &Second_ob; // Присвоєння адреси об'єкта похідного класу

p->who(); /* Тут виконується звернення до функції who() класу baseClass,

оскільки у класі secondD вона не перевизначена. */

getch(); return 0;

}

Тепер у процесі виконання цієї програми на екран виводиться таке:

Базовий клас.

Перший похідний клас.

Базовий клас.

Як підтверджують отримані результати виконання цієї програми, оскільки функція who() не перевизначена похідним класом secondD, то під час її виклику за допомогою настанови p->who() (коли член р вказує на об'єкт Second_ob) виконується та версія функції who(), яку було визначено у базовому класі baseClass.

Варто знати! Успадковані властивості специфікатора virtual є ієрархічними. Тому, якщо попередній приклад змінити так, щоб клас secondD був виведений з класу firstD, а не з класу baseClass, то під час звернення до функції who() через об'єкт типу secondD буде викликано ту її версію, яка оголошена у похідному класі firstD, оскільки цей клас є "найближчим" (за ієрархічними "мірками") до класу secondD, а не функцію who() з тіла базового класу baseClass. Ці ієрархічні залежності демонструються на прикладі наведеної нижче програми.

Код програми 16.4. Демонстрація ієрархічної залежності

#include <iostream> // Для потокового введення-виведення

using namespace std; // Використання стандартного простору імен

class baseClass { // Оголошення базового класу

public:

virtual void who() { cout << "Базовий клас.\n";}

};

// Клас firstD виведений з класу baseClass

class firstD : public baseClass {

public:

void who() { cout << "Перший похідний клас.\n";}

};

// Клас secondD тепер виведений з класу firstD, а не з класу baseClass.

class secondD : public firstD {

// Функція who() не визначена.

};

int main()

{

baseClass Base_ob; // Створення об'єкта базового типу

baseClass *p; // Створення покажчика на об'єкт базового типу

firstD First_ob; // Створення об'єкта похідного типу

secondD Second_ob; // Створення об'єкта похідного типу

p = &Base_ob; // Присвоєння адреси об'єкта базового класу

p->who(); // Доступ до функції who() класу baseClass

p = &First_ob; // Присвоєння адреси об'єкта похідного класу

p->who(); // Доступ до функції who() класу firstD

p = &Second_ob; // Присвоєння адреси об'єкта похідного класу

p->who(); /* Тут виконується звернення до функції who()

класу firstD, оскільки у класі secondD її не перевизначено. */

getch(); return 0;

}

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

Базовий клас.

Перший похідний клас.

Перший похідний клас.

Як бачите, клас secondD тепер використовує версію функції who(), яка визначена| у класі firstD, оскільки вона знаходиться щонайближче в ієрархічному ланцюжку класів.