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

7.10.3. Віртуальні деструктори

Деструктори, на відміну від конструкторів, можуть бути віртуальними. Синтаксично вони задаються, як і звичайні віртуальні функції, за допомогою ключового слова virtual. Віртуальні деструктори використовуються у випадку, коли в деякому класі необхідно знищити об'єкти похідного класу, на які посилаються покажчики на базовий клас. Розглянемо приклад:

class Base{

private:

char*sp1;

public:

Base(const char*s)

{sp1=strdup(s);}

virtual ~Base()

{delete sp1;}};

class Derived::public Base{

private:

char*sp2;

public:

Derived(const char*s1,const char*s2):Base(s1)

{sp2=strdup(s2);}

virtual~Derived()

{delete sp2;}};

Base*pbase;

pbase=new Derived("string1","string2");

delete pbase; //s1-знищився,s2-залишився.

Якщо б у цьому прикладі деструктори не були віртуальними, то при виході з області видимості об'єкта класу Derived, на який указує покажчик pbase, викликався б лише деструктор класу Base, тобто копія рядка string2 залишилася б у пам'яті. Якщо ж деструктори оголошені як віртуальні, то в даній ситуації буде викликаний спочатку деструктор похідного класу, а потім – базового.

7.10.4. Посилання як засіб для реалізації поліморфізму

Для реалізації поліморфізму в С++, крім покажчиків, можна використовувати й посилання. Розглянемо приклад:

#include "form.h"

main

{circle c1;

Line l1,l2;

shape & pic0=c1

shape & pic1=l1;

shape & pic2=l2;

pic0.Draw();

pic1.Draw();

pic2.Draw();}

У цьому прикладі кожен виклик функції Draw() приводить до зображення відповідної фігури.

При передаванні параметрів віртуальним функціям може виникнути помилка. Виникає питання: коли здійснюється контроль за помилками при передаванні параметрів? Адже конкретна реалізація віртуальної функції зв'язується з об'єктом на етапі виконання програми. Що стосується С++, то контроль за помилками при передаванні параметрів віртуальним функціям здійснюється на етапі компіляції, а не виконання програми, тому що сигнатури віртуальних функцій мають строго збігатися.

7.10.5. Дещо про механізм віртуальних функцій

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

classname*object;

object->message(15);,

то компілятором він перетворюється на

classname_message(object,15);

Механізм віртуальних функцій у С++ забезпечується за допомогою таблиць віртуальних функцій (ТВФ), які мають такі властивості:

1. ТВФ будується компілятором автоматично для кожного класу, який має віртуальні функції й містить їх адреси, доступні в цьому класі.

2. Кожний екземпляр класу містить скритий покажчик на його ТВФ.

3. Компілятор автоматично вставляє в початок конструктора класу фрагмент коду, який ініціалізує покажчик на ТВФ кожного класу.

4. Для будь-якої ієрархії класів адреса деякої віртуальної функції має одне й те саме зміщення у ТВФ кожного класу.

5. Під час виклику віртуальних функцій код, згенерований компілятором, перш за все знаходить покажчик віртуальної таблиціi, потім відбувається звертання до ТВФ і знаходиться адреса віртуальної функції, i лише після цього відбувається її безпосередній виклик. Наприклад:

class Parent

{int value;

public: