Программирование >>  Инициализация объектов класса, структура 

1 ... 307 308 309 [ 310 ] 311 312 313 ... 395


свои имена: Линь-Линь, Маугли или Балу. Каждое животное принадлежит к какому-то виду; скажем, Линь-Линь - это гигантская нанда. Вид: в свою очередь входят в семейства. Так, гигантская нанда - член семейства медведей, хотя, как м1 увидим в разделе 18.5, но этому поводу в зоологии долго велись бурные дискуссии. Каждое семейство - член животного мира, в нашем случае ограниченного территорией зоопарка.

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

Помимо классов, описывающих животных, есть и вспомогательные классы, инкапсулирующие различные абстракции иного рода, например животные, находящиеся под угрозой вымирания . Наша реализация класса Panda множественно наследует от Bear (медведь) и Endangered (вымирающие).

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

Для поддержки множественного наследования синтаксис списка базовых классов

class Bear : public ZooAnimal { ... };

расширяется: допускается наличие нескольких базовых классов, разделенных запятыми:

class Panda : public Bear, public Endangered { ... };

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

Язык не накладывает никаких ограничений на число базовых классов, которым может наследовать производный. На практике чаще всего встречается два класса, один из которых представляет открытый абстрактный интерфейс, а второй - закрытую реализацию (хотя ни один из рассмотренных выше примеров этой модели не следует). Производные классы, наследующие от трех или более базовых, - это пример такого стиля проектирования, когда кажд1й базовый класс представляет одну грань полного интерфейса производного.

В случае множественного наследования объект производного класса содержит но одному нодобъекту каждого из своих базовых (см. раздел 17.3). Например, когда мы пишем

Panda ying yang;

то объект ying yang будет состоять из подобъекта класса Bear (который в свою очередь содержит подобъект ZooAnimal), подобъекта Endangered и нестатических членов, объявленных в самом классе Panda, если таковые есть (см. рис. 18.3).






Рис. 18.3. Иерархия множественного наследования класса Panda

Конструкторы базовых классов вызываются в порядке объявления в списке базовых классов. Например, для ying yang эта последовательность такова: конструктор Bear (но поскольку класс Bear - производный от ZooAnimal, то сначала вызывается конструктор ZooAnimal), затем конструктор Endangered и в самом конце конструктор Panda.

Как отмечалось в разделе 17.4, на порядок вызова не влияет ни наличие базовых классов в списке инициализации членов, ни порядок их перечисления. Иными словами, если бы конструктор Bear вызывался неявно и потому не был бы упомянут в списке

конструктор по умолчанию класса Bear вызывается до ёИпбббёбгба ёёаппа Endangered п aaoly аба61а16а1ё . . .

Panda::Panda()

: Endangered( Endangered::environment, Endangered::critical )

инициализации членов, как в следующем примере:

то все равно конструктор по умолчанию Bear был бы вызван раньше, чем явно заданный в списке конструктор класса Endangered с двумя аргументами.

Порядок вызова деструкторов всегда противоположен порядку вызова конструкторов. В нашем примере деструкторы вызываются в такой последовательности: ~Panda(), ~Endangered (), ~Bear(), ~ZooAnimial().

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

Однако такую ошибку вызывает не потенциальная неоднозначность неквалифицированного доступа к одному из двух одноименных членов, а лишь попытка фактического обращения к нему (см. раздел 17.4). Например, если в обоих классах Bear и Endangered определена функция-член print() , то инструкция

ying yang.print( cout ); приводит к ошибке компиляции, даже если у двух унаследованных функций-членов

Error: ying yang.print( cout ) -- ambiguous, one of Bear::print( ostreamS )

разные списки параметров.



Сшибка: ying yang.print( cout ) - неоднозначно, одна из Bear::print( ostream& )

Endangered::print( ostream&, int ) Endangered::print( ostream&, int )

Причина в том, что унаследованные функции-члены не образуют множество перегруженных функций внутри производного класса (см. раздел 17.3). Поэтому print() разрешается только но имени, а не но тинам фактических аргументов. (О том, как производится разрешение, мы поговорим в разделе 18.4.)

В случае одиночного наследования указатель, ссылка или объект производного класса при необходимости автоматически преобразуются в указатель, ссылку или объект базового класса, которому открыто наследует производный. Это остается верным и для множественного наследования. Так, указатель, ссылку или сам объект класса Panda

extern void display( const Bear& ); extern void highlight( const Endangered& );

Panda ying yang;

display( ying yang ); i6aaeeuii highlight( ying yang ); i6aaeeuii

extern ostream&

operator ( ostream&, const ZooAAnimalS );

можно преобразовать в указатель, ссылку или объект ZooAnimal, Bear или Endangered:

cout << ying yang << endl; правильно

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

extern void display( const Bears );

намного выше. Рассмотрим, к примеру, две функции:

extern void display( const EndangeredS );

Panda ying yang;

Неквалифицированный вызов display() для объекта класса Panda

display( ying yang ); ошибка: неоднозначность

приводит к ошибке компиляции:

Error: display( ying yang ) - aiguous, one of

display( const Bears );

display( const EndangeredS ); Сшибка: display( ying yang ) -- неоднозначно, одна из

display( const Bears );

display( const EndangeredS );



1 ... 307 308 309 [ 310 ] 311 312 313 ... 395

© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика