Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекції ООП1.doc
Скачиваний:
7
Добавлен:
17.11.2019
Размер:
553.98 Кб
Скачать

Віртуальні функції.

Вказівник this

Ім'я this є службовим (ключовим) словом. Явно описати чи визначити вказівник this не можна. Відповідно до неявного визначення this є константним вказівником, тобто змінювати його не можна, однак у кожної приналежної класу функції він указує саме на той об'єкт, для якого функція викликається. Говорять, що вказівник this є додатковим (схованим) параметром кожної нестатичної компонентної функції. Іншими словами, при вході в тіло приналежній класу функції вказівник this ініціалізується значенням адреси того об'єкта, для якого викликана функція. Об'єкт, що адресується вказівником this, стає доступним усередині приналежної класу функції саме за допомогою вказівника this. При роботі з компонентами класу усередині приналежної класу функції можна було б скрізь використовувати цей вказівник. Наприклад, зовсім правильним буде таке визначення класу:

class ss

{ int si;

char sc;

ss (int in, char en) // Конструктор об'єктів класу з аргументами створює обєкт з деякими початковими значеннями.

{ this -> si = in; this -> sc = en; }

void print (void) //Функція висновку відомостей про об'єкт.

{ cout << “\n si = “ << this -> si;

cout << “\n sc = “ << this -> sc; }

};

Віртуальні функції.

Ми вже згадували про поліморфізм - важливої особливості об'єктно- орієнтованого програмування. Поліморфізм – це можливість використовувати одинакові імена для методів різних класів. Розглянемо наступний приклад:

#include <iostream.h>

class X

{

public:

double A(double x)

{ return x * x; }

double B(double x)

{ return A(x)/2; }

};

class Y: public X \\ X підклас У, X- має доступ до захищених елементів

класу У.

{

public:

double A(double x)

{ return x * x * x; }

};

int main ( )

{

Y y;

cout << y.B(3) << endl;

return 0;

}

У класі X оголошуються функції А і В, причому функція В викликає

функцію А. Клас Y, нащадок класу X, успадковує функцію В, але

перевизначає функцію А. Мета цього прикладу - демонстрація поліморфної поведінки класу У. Ми повинні одержати наступний результат: виклик успадкованої функції Х::В повинен привести до виклику функції Y::А. Що ж видасть нам наша програма? Відповіддю буде 4.5, а не 13.5! В чому ж справа? Чому компілятор дозволив вираз y.В(З) як виклик успадкованої функції Х::В, яка, у свою чергу, викликає Х::А, а не функцію Y::А, що повинне було б відбутися у разі поліморфної реакції класу?

Віртуальні функції оголошуються таким чином (синтаксис):

class className1

{

// фуикції-елементи

virtual <тип, що повертається > < ім'я функції > ( <список параметрів > );

};

class className2 : public className1

{

// функції-елементи

virtual < тип, що повертається > < ім'я функції > ( < список параметрів > );

};

Приклад, що показує, як за допомогою віртуальних функцій можна реалізувати поліморфну поведінку класів X і Y:

#include < iostream.h >

class X

{

public:

virtual double A(double x) { return x * x; }

double B(double x) { return A(x)/2; }

};

class Y: public X

{

public:

virtual double A(double x) { return x * x * x; }

};

main ( )

{

Y y;

cout << y. B(3) << endl;

return 0;

}

Цей приклад виведе вам правильне значення 13.5, тому що в результаті виклику успадкованої функції Х::В, що викликає функцію А, як функція А під час виконання програми буде використана заміщаюча функція Y::А. Правило віртуальної функції свідчить:

"Віртуальна одного разу - віртуальна завжди".

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

Правило це справедливо і для всіх мов об'єктно-орієнтованого програмування, що підтримують віртуальні функції, але не допускаючих перевантаження функцій. У С++ положення декілька інше. Ви можете оголошувати невіртуальні переобтяжені функції, співпадаючі по імені з віртуальними функціями, але що мають інший список параметрів. І, крім того, ви не можете успадковувати невіртуальні функції, ім'я яких співпадає з віртуальними функціями. Розглянемо приклад 8, що ілюструє сказане.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]