Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Курс лекцій.doc
Скачиваний:
15
Добавлен:
03.11.2018
Размер:
1.12 Mб
Скачать

7.3 Конструктори та деструктори в похідних класах

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

Деструктори не вимагають таких строгих правил при їх використаннi. В похiдному класi деструктор потрiбен лише при наявностi членiв, якi необхiдно видалити при виході об’єкта з області видимості.

Розглянемо базовий клас , оголошений наступним чином:

class Tbase

{ private:

char * basep;

public:

TBase (cout char * s) {basep=strdup(s);}

~TBase() {delete basep;}

const char * GetStr(void) {return basep;}

};

Конструктор класу викликає бiблiотечну функцiю strdup() для створення копiї рядкового аргументу у виглядi динамiчної змiнної з присвоєнням адреси видiленої пам'ятi вказiвнику basep. Деструктор звільняє цей блок пам’яті.

При створеннi об'єкта типу:

TBase president("Georje Washington");

конструктору класу передається рядок "Georje Washington", при цьому вiн створює копію рядка i присвоює її адресу члену basep об'їкта president. Коли president виходить з областi видимостi, деструктор знищує рядок.

Оголосимо похiдний клас наступним чином:

class TDerived: public TBase

{ private:

char * uppercasep;

public:

TDerived (cout char * s)

~TDerived() {delete uppercasep;}

const char * GetStr(void) {return uppercasep;}

};

До полiв , наслiдуваних з TBase, Tderived добавляє закритий член, символьний вказiвник uppercasep, який посилаеться на копiю рядка, що

зберiгається в Tbase, з символами, перетвореними на малі. Деструктор похідного класу знищує цей новий рядок.

Конструктор Tderived можна реалiзувати так:

TDerived()::TDerived(const char * s)

:TBase()

{uppercasep=strupr(strdup(s));

};

Конструктор TDerived викликає конструктор TBase , який помiщує рядок, на який посилається s , в кучу та iнiцiалiзує basep адресою копiї цього рядка. Пiсля цього конструктор похiдного класу створює ще одну копiю рядка, перетворюючи її символи в маленьки та присвоюючи uppercase адресу цiєї копiї рядка.

Якщо ми створюємо об'єкт типу TDerived, то при цьому створюється двi копiї рядка. Розглянемо наступний приклад:

TDeriver president("Georje Washington");

count<<"original shing:<<president.GetStr()<<'\n';

count<<"uppecasep shing:<<president.GetStr()<<'\n';

Результат:

original shing: George Washington

uppecasep shing: GEORGE WASHINGTON

При виходi з областi видимостi C++ автоматично викликає деструктори в зворотньому порядку по ієрархії наслідування: від похідного класу до базового. Так при виході об’єкта класа president з області видимості спочатку викликається деструктор похідного класу, який виконує оператор delete uppercasep, а потім конструктор базового, що виконує оператор delete basep. На відміну від конструкторів, деструктори похідного класу ніколи не викликає безпосередньо деструктор базового класу (деструктор класу можна викликати безпосередньо як функцію-член).

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

class base

{ public:

base (char * n, shint t);

~base();

};

class derived : public base

{ base m;

public:

derived (char * n);

~derived();

};

derived::derived(char * n):(n,10),m("member",123)

{ // ........}

Бачимо , що параметри конструктора члена класу m вказуються при виклиці конструктора похідного класу.