Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ЯМП ответы.doc
Скачиваний:
0
Добавлен:
28.12.2019
Размер:
710.66 Кб
Скачать

30.Множественное наследование.

Класс может быть порождён из любого числа базовых классов. Наличие более чем одногонепосредственного базового класса называется множественным наследованием. class A { ... }; class B { ... }; class C { ... }; class D : public A, public B, private C { ... }; Указатель на производный класс можно передать в функции, которые ожидают указатель на один из базовых классов. Реализация этого механизма подразумевает простые методы компиляции для обеспечения того, что функция, ожидающая указатель на один базовый класс, увидит часть производного класса, отличную от той, которую увидит функция, ожидающая указатель на другой базовый класс. Виртуальные функцииработают как обычно. class A

{ public:

void f1();

virtual void g() = 0; };

class B

{ public:

void f2();

virtual void h() = 0; };

class C : public A, public B

{ public:

void g(); // Замещение A::g()

void h(); // Замещение B::h()

};

void f1(A *p) { p->f1(); }

void f2(B *p) { p->f2(); }

void main()

{ C c;

f1(&c);

f2(&c);

A *p = &c;

p->g(); // Правильно

p->h(); // Ошибка: функция h не является членом класса А

dynamic_cast<B *>(p)->h(); // Правильно

}

Класс не может быть задан в качестве непосредственного базового класса более одного раза, но он может быть более одного раза косвенным базовым классом.

class A { ... };

class B : public A, public A { ... };

// Ошибка!

class A { ... };

class B : public A { ... };

class C : public A { ... };

class D : public B, public C { ... };

// Всё правильно

Здесь объект класса D будет иметь два подобъекта класса A.

Производный класс и его базовые классы могут быть представлены в виде направленного ациклического графа.

Класс не может появляться дважды в списке базовых классов просто потому, что каждая ссылка на него или его члены была бы неоднозначной. Эта проблема не возникает, если класс появляется дважды в качестве косвенного базового класса. Объект класса D имеет два подобъекта класса A – B::A и C::A.

Поскольку в объекте D имеется два объекта A, приведение (явно или неявное) между указателем на A и указателем на D неоднозначно и поэтому запрещено.

D *pd = new D;

A *pa = pd;

pa = (A *)pd;

pa = (B *)pd;

pa = (С *)pd;

// Неоднозначность!

// Всё равно неоднозначность!

// Приведение к указателю на A в объекте B

// Приведение к указателю на A в объекте С

Однако класс может быть одновременно непосредственным и косвенным базовым классом.

class A { ... };

class B : public A { ... };

class C : public A { ... };

class D : public A, public B, public C { ... };

pa = pd;

pa = (B *)pd;

pa = (С *)pd;

// Можно!

// Приведение к указателю на A непосредственно в объекте D

// Приведение к указателю на A в объекте B

// Приведение к указателю на A в объекте С