Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
первая часть.doc
Скачиваний:
26
Добавлен:
07.02.2016
Размер:
2.19 Mб
Скачать

Віртуальні методи

Робота з об’єктами найчастіше робиться через покажчики. Покажчикові на базовий клас можна привласнити значення адреси об'єкта будь-якого похідного класу, наприклад:

// Описується покажчик на базовий клас:

monstr *р;

// Покажчик посилається на об'єкт похідного класу:

р = new daemon;

Виклик методів об'єкта відбувається відповідно до типу покажчика, а не за фактичним типом об'єкта, на який він посилається, тому при виконанні оператора, наприклад,

p->draw(1, 1, 1, 1);

буде викликаний метод класу monstr, а не класу daemon, оскільки посилання на методи дозволяються під час компонування програми. Цей процес називається раннім зв'язуванням. Щоб викликати метод класу daemon, можна використовувати явне перетворення типу покажчика:

(daemon * p)->draw(1, 1, 1, 1);

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

У C++ реалізовано механізм пізнього зв'язування, коли дозвіл посилань на метод відбувається на етапі виконання програми в залежності від конкретного типа об'єкта, що визвав цей метод. Цей механізм реалізовано за допомогою віртуальних методів і розглянуто далі.

Для визначення віртуального методу використовується специфікатор virtual, наприклад:

virtual void draw(int x, int y, int scale, int position);

Розглянемо правила опису і використання віртуальних методів.

  • Якщо в базовому класі метод визначений як віртуальний, метод, визначений у похідному класі з тим же ім'ям і набором параметрів, автоматично стає віртуальним, а з набором параметрів - звичайним.

  • Віртуальні методи успадковуються, тобто перевизначати їх у похідному класі потрібно тільки при необхідності задати дії, що відрізняються. Права доступу при перевизначенні змінити не можна.

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

  • Віртуальний метод не може з'являтися з модифікатором static, але може бути оголошений як дружній.

  • Якщо в класі вводиться опис віртуального методу, він повинний бути визначений хоча б як чисто віртуальний.

Чисто віртуальний метод містить ознаку = 0 замість тіла, наприклад:

virtual void f(int) = 0;

Чисто віртуальний метод повинний перевизначатися в похідному класі (можливо, знову як чисто віртуальний).

Якщо визначити метод draw у класі monstr як віртуальний, рішення про те, метод якого класу викликати, буде прийматися в залежності від типу об'єкта, на який посилається покажчик:

monstr *r, *р;

г = new monstr; //Створюється об'єкт класу monstr

р = new daemon; //Створюється об'єкт класу daemon

r->draw(1, 1, 1, 1); //Викликається метод monstr::draw

p->draw(1, 1, 1, 1); //Викликається метод daemon::draw

р-> monstr::draw(1, 1, 1, 1); //Обхід механізму віртуальних методів

Якщо об'єкт класу daemon буде викликати метод draw не безпосередньо, а побічно (тобто з іншого методу, визначеного в класі monstr), буде викликаний метод draw класу daemon.

Отже, віртуальним називається метод, посилання на який дозволяється на етапі виконання програми (переклад красивого англійського слова virtual — у даному значенні всього-на-всього «фактичний», тобто посилання дозволяється по факту виклику).