Class D:public B,public C

{//...}

Main()

{D d;

d.func();}

Одразу виникає синтаксичне питання: яка функція func() викликається – успадкована класом В чи С? Формально тут присутній розглянутий вище конфлікт імен. Бачимо, що у випадку, коли один клас успадковується іншим кілька разів (через множинне успадкування), можуть виникнути негативні моменти. Такі помилки виявляються на етапі компіляції. У прикладі клас A успадковується у D два рази, будучи базовим для класів В i С. Очевидно, що проблеми можуть виникнути й у тому випадку, коли класи В та С мають конструктори, які iнiцiалiзують поле data. Тоді клас D також повинен мати конструктор, хоча б для того, щоб викликати конструктори базових класів. Однак при цьому виникне неоднозначність при iнiцiалiзацiї поля data.

Визначимо ще один клас:

class E:

Public A,

Public D

{\\...}

У цьому випадку також на етапі компіляції з'явиться помилка:

A is inaccessible becouse also in D

(А недоступний, оскільки він уже в D). Для виходу із таких ситуацій використовуються віртуальні базові класи.

Віртуальні базові класи. Синтаксично для оголошення базового класу віртуальним достатньо в базовому списку вказати ключове слово virtual перед атрибутом доступу:

class<ім’я похідного класу>:virtual<атрибут доступу><ім’я базового класу>,...

Семантично така конструкція вказує компілятору, що у випадку множинного успадкування береться до уваги лише одна копія базового класу. При цьому ліквідується небезпека повторного успадкування. Ключове слово virtual має бути присутнім у всіх випадках, де можливе повторне успадкування базового класу. Якщо в нашому прикладі оголосити базовий клас А віртуальним, то жодних негативних моментів, пов'язаних із повторним успадкуванням, не буде:

Class A

{protected:

int data;

public:

void func(void){//тіло}};

Class B:virtual public A

{//...};

Class C:virtual public A

{//...};

Class D:public B,public C

{//...};

Class E

:virtual public A,

Public D

{//...};

Main()

{D d;

d.func();}

Бачимо, що в описі класів В i С присутнє слово virtual. При цьому ситуація змінюється таким чином: якщо клас А успадковується в кількох класах, то він не дублюватиметься. Розглянемо приклад:

class Company {

private:

char*name;

public:

company(const char*s){name=strdup(s);}

void Display(void){cout<<name<<'\n'}

};

class CocaCola:virtual public Company {

public:

CocaCola(void):Company("CocaCola") { }

};


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: