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

Int mainO

// Створення об'єкта базового типу // Створення покажчика на об'єкт базового типу // Створення об'єкта похідного типу // Створення об'єкта похідного типу

// Присвоєння покажчику адреси об'єкта базового класу // Доступ до функції ЄІіошО класу ЬазеСІазз

// Присвоєння покажчику адреси об'єкта похідного класу // Доступ до функції ЄІіошО класу йгеЮ

// Присвоєння покажчику адреси об'єкта похідного класу // Доступ до функції ЄІіошО класу БесопгіО

{

baseClass ObjB; baseClass *bp; firstD ObjF; secondD ObjS;

bp = &ObjB; bp->Show();

bp = &ObjF; bp->Show();

bp = &ObjS; bp->Show(); getchO; return 0;

}

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

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

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

Другий похідний клас.

Розглянемо детально код цієї програми, щоб зрозуміти, як вона працює.

У класі ЬазеСІазБ функція Зііо\л/() оголошена віртуальною. Це означає, що її можна перевизначити у похідному класі (у класі, виведеному з ЬазеСІазБ). І вона дійсно перевизначається в обох похідних класах йгбЮ і бєсопсЮ. У основній функції таіп() оголошуються чотири змінні: ОЬІВ - об'єкт типу ЬазеСІазБ, Ьр - покажчик на об'єкт класу ЬазеСІазБ, а також два об'єкти 0^ і двох похідних класів йгеЮ і бє- сопсЮ відповідно. Потім покажчику Ьр присвоюється адреса об'єкта ОЬІВ і викли­кається функція Зііо\л/(). Оскільки функцію Зііо\л/() оголошено віртуальною, то мова С++ у процесі виконання програми визначає, до якої саме версії функції Зііо\л/() тут потрібно звернутися, причому рішення приймається шляхом аналізу типу об'єкта, який адресується покажчиком Ьр. У цьому випадку покажчик Ьр вказує на об'єкт типу ЬазеСІазБ, тому спочатку виконується та версія функції Зііо\л/(), яку оголошено у базовому класі ЬазеСІазБ. Потім покажчику Ьр присвоюється адреса об'єкта ОЬІР. Як зазначалося вище, за допомогою покажчика на базовий клас можна звертатися до об'єкта будь-якого його похідного класу. Тому, коли функція Зііо\д/() виклика­ється удруге, мова С++ знову з'ясовує тип об'єкта, який адресує покажчик Ьр, і, ви­ходячи з цього типу, визначає, яку версію функції Зііо\л/() потрібно викликати. Ос­кільки покажчик Ьр тут вказує на об'єкт типу йгеЮ, то виконується версія функції Зііо\д/(), яку визначено у похідному класі йгеЮ. Аналогічно після присвоєння покаж­чику Ьр адреси об'єкта викликається версія функції Зііо\д/(), яку оголошено у похідному класі бєсопсЮ.

Нео! хідноапам ятати! Те, яка версія віртуальної функції дійсно буде вик­ликана, визначається у процесі виконання програми. Відповідне рішення ґрун­тується виключно на аналізі типу об'єкта, який адресується покажчиком на базовий клас.

Віртуальну функцію можна викликати звичайним способом (не через покаж­чик), використовуючи оператор "крапка" і задаючи ім'я об'єкта, який викли­кається. Це означає, що у наведеному вище прикладі було б синтаксично коректно звернутися до функції вИошО за допомогою такої настанови:

ОЬІР.ЗІто\л/();

Проте під час виклику віртуальної функції у такий спосіб ігноруються її полі­морфні атрибути. І тільки під час звернення до віртуальної функції через покаж­чик на базовий клас досягається динамічний поліморфізм.

Якщо віртуальна функція перевизначається у похідному класі, то її називають переви наченою.

Спочатку може видатися дивним, що перевизначення віртуальної функції у похідному класі є спеціальною формою перевизначення функцій. Але це не так. Насправді ми маємо справу з двома принципово різними процесами. Передусім, різні версії перевизначеної функції мають відрізнятися одна від іншої типом і/або кількістю параметрів, тоді ж тип і кількість параметрів у різних версіях віртуаль- ної функції мають точно збігатися. І справді, прототипи віртуальної та перевизна- ченої функцій мають бути абсолютно однаковими. Якщо прототипи будуть різни­ми, то такі функції просто вважатимуться перевизначеними, а їх "віртуальна суть" втратиться. Окрім цього, віртуальна функція повинна бути членом класу, для яко­го вона визначається, а не його "другом". Водночас віртуальна функція може бути "другом" іншого класу.

Вартоа нати! Функціям деструкторів дозволено бути віртуальними, а фун­кціям конструкторів - ні.