Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методические указания.doc
Скачиваний:
9
Добавлен:
18.04.2015
Размер:
619.52 Кб
Скачать
  1. Множественное наследование классов

Класс может служить базовым сразу для нескольких производных классов. Во многих случаях взаимодействие концепций, привлекаемых к решению задачи (формализацией чего является взаимодействие классов в программе), требует отношений более общего вида. Такие отношения могут быть получены в случае, когда производный класс строится на основе нескольких базовых; при этом говорят о множественном наследовании классов.

Внешне построение производного класса на основе нескольких базовых выглядит так: вместо имени одного базового класса (вместе с его атрибутом – public или private) используется список имен, разделенных запятыми. Например:

class A { /* … */ };

class B { /* … */ };

class C: public A, private B { /* … */};

Как обычно, атрибут private может быть опущен. Передача аргументов конструкторам базовых классов из конструктора производного класса производится так же, как и в случае без множественного наследования:

C::C (int a, char * str):A(a),B(str) { /* … */ }

Но реализация множественного наследования привела к появлению целого ряда проблем, главными из которых являются три:

а) как поступить, если в объект производного типа будут входить более одного объекта одного и того же базового типа;

б) как выбрать нужный член класса, если его имя присутствует более чем в одном базовом классе, и что при этом считать неопределенностью;

в) в каком порядке должно происходить создание и уничтожение подобъектов.

При построении производного класса с использованием множественного наследования упоминание в списке базовых классов одного и того же класса более одного раза запрещено:

class B : public A, public A { /* … */ }; // ошибка

Тем не менее, один и тот же базовый класс может использоваться при построении производного класса более одного раза следующим образом:

class Base { /* … */ };

class A : public Base { /* … */ };

class B : public Base { /* … */ };

class Derived : public A, public B { /* … */ };

В этом случае объект типа Derived будет содержать два различных подобъекта типа Base. Существуют ситуации в которых необходимо, чтобы подобъект типа Base в объекте типа Derived появился только один раз. Язык C++ позволяет программисту реализовать оба варианта.

Обеспечить создание только одного подобъекта базового типа можно, описав данный класс как виртуальный базовый класс:

class Base { /* … */ };

class A : public virtual Base { /* … */ };

class B : public virtual Base { /* … */ };

class Derived : public A, public B { /* … */ };

Теперь при создании объекта типа Derived будет создан только один подобъект типа Base, и его члены будут использоваться функциями-членами как класса A, так и B.

Правила создания подобъектов при использовании множественного наследования можно сформулировать следующим образом:

а) При отсутствии виртуальных базовых классов сначала происходит создание подобъектов базовых типов, причем эти подобъекта создаются в том же порядке, в котором соответствующие классы появились в списке базовых классов для данного производного класса; после этого происходит инициализация данных – членов производного класса в том порядке, в котором они появились в определении этого класса; и, наконец, выполняется конструктор производного класса. Деструкторы вызываются в обратном порядке.

б) При наличии виртуальных базовых классов они создаются до любого из своих производных классов; виртуальные базовые классы создаются ранее невиртуальных базовых классов; виртуальные базовые классы из списка создаются в порядке их появления в списке.

До сих пор все, что говорилось о производных классах, сводится к следующему: концепция производных классов – просто более удобный способ построения нового класса. Но преимущество концепции производных классов не исчерпывается удобством создания. Важным является то обстоятельство, что производный класс рассматривается не как совершенно самостоятельный класс, а как свой базовый класс с некоторыми дополнительными возможностями.