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

7.9.4. Використання заміщуючих функцій-членів

У похідному класі зазвичай додаються нові дані та функції-члени. Однак існує можливість заміни (заміщення) функцій-членів, успадкованих з базового класу. Розглянемо такий клас Base:

class Base

{private:

char*sptr;

public:

Base(const char*s){sptr=strdup(s);}

~Base(){delete sptr;}

void Display(void){cout<<sptr<<'\n';}};

Можна оголосити об'єкт типу Base:

Base region("Rivne");

i вивести рядок: region.Display().

Припустимо, що пізніше ми вирішили, що всі подібні рядки мають починатися рядком "Region:". Можна досягти цього так:

cout<<"Region:";

region.Display();

Однак зміни потрібно вносити в усю програму. Кращий варіант розв'язання проблеми – вивести новий клас з Base та замінити успадковану функцію-член Dispay() модифікованою версією.

Можна описати похідний клас таким чином:

class Region:public Base

{public:

Region (const char*s):Base(s){ }

Void Display (void); //замiщувальна функцiя

};

Бачимо, що тут оголошена функція-член, абсолютно ідентична відповідній функції базового класу. При роботі це означає, що вона заміщує базову. Можемо реалізувати її так:

Void Region::Display(void)

{cout<<"Region:";

Base.Display(); //виклик замiщеної функцiї-члена

};

Оголошення й використання об’єкта класу

Region region("Rivne");

region.Display();

приведе до друку рядка "Region:Rivne".

Аналогічно можна вчинити i з конструкторами в похідних класах. Припустимо, що нам необхідно мати кілька класів з різними назвами областей. Можна написати клас для кожної області, подібний до такого:

class Rivne:public Region

{public:

Rivne():Region("Rivne"){}};

Новий конструктор похідного класу, оголошений без параметрів, передає рядок Rivne конструктору базового класу. Далі створюється об'єкт R і виводиться назва області (міста):

Rivne R;

R.Display();

Конструктори можуть мати довільні параметри. Нехай нам потрібен клас, який зберігає, крім назви області, ще й кількість населення. Можна вивести його з Region:

class Population:public TRegion

{private:

long population;

public:

Population(long n,const char*name);

Void Display(void);};

Population::Population(long n,const char*name)

{population=n;

Region(name);};

Void Population::Display(void)

{Region::Display();

cout<<"Population::"<<population<<'\n';};

Далі використовувати його можна так:

Population Kyiv(3500000,"Kyiv");

Kyiv.Display();

7.9.5. Похідні класи й покажчики

Якщо похідний клас derived має відкритий базовий клас base, то покажчик на derived можна присвоювати змінній типу покажчик на Base без використання явного перетворення типу. Обернене перетворення покажчика на base у покажчик на derived має бути явним. Наприклад:

class base {

//...

};

class derived:public base

{

//...

};

derived m;

base*pb=& m; //неявне перетворення

derived*pd;

pd=(derived*)pb; //явне перетворення

Іншими словами, об'єкт похідного класу при роботі з ним через покажчик можна розглядати як об’єкт базового класу. Обернене невірно.

Якщо base є закритим базовим класом для derived, то неявне перетворення derived* на base* не виконується:

class base

{int m1;

public:

int m2;};

class derived:base

{//m2 - закритий тип derived

};...

derived d;

d.m2=2; //помилка

base*pb=&d; //помилка

base*pb; //ok

pb->m2=2; //ok