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

1 ... 317 318 319 [ 320 ] 321 322 323 ... 395


The family name for meeko is Raccoon

(Название семейства для meeko - это Raccoon) Если же объявить объект типа Panda:

Panda yolo( yolo );

то ближайшим производным классом для объекта yolo будет Panda, поэтому он и отвечает за инициализацию ZooAnimal.

Когда инициализируется объект Panda, то явные вызовы конструктора ZooAnimal в конструкторах классов Raccoon и Bear не выполняются, а вызывается он с теми аргументами, которые указаны в списке инициализации членов объекта Panda. Вот так

Panda::Panda( string name, bool onExhibit=true )

: ZooAnimal( name, onExhibit, Panda ), Bear( name, onExhibit ), Raccoon( name, onExhibit ), Endangered( Endangered::environment,

Endangered::critical ), sleeping( false )

выглядит реализация:

Если в конструкторе Panda аргументы для конструктора ZooAnimal не указаны явно, то вызывается конструктор ZooAnimal по умолчанию либо, если такового нет, выдается ошибка при компиляции определения конструктора Panda.

Когда мы пишем:

cout << yolo.family name() ;

печатается строка:

The family name for yolo is Panda

(Название семейства для yolo - это Panda)

Внутри определения Panda классы Raccoon и Bear являются промежуточными, а не ближайшими производными. В промежуточном производном классе все прямые вызовы конструкторов виртуальных базовых классов автоматически подавляются. Если бы от Panda был в дальнейшем произведен еще один класс, то сам класс Panda стал бы промежуточным и вызов из него конструктора ZooAnimal также был бы подавлен.

Обратите внимание, что оба аргумента, передаваемые конструкторам Bear и Raccoon, излишни в том случае, когда они выступают в роли промежуточных производных классов. Чтобы избежать передачи ненужных аргументов, мы можем предоставить явный конструктор, вызываемый, когда класс оказывается промежуточным производным. Изменим наш конструктор Bear:

печатается строка:



class Bear : public virtual ZooAnimal { public:

ес выступает в ро бижаего производного класса Bear( string name, bool onExhibit=true )

: ZooAnimal( name, onExhibit, Bear ), dance( two left feet )

... остальное без изменения protected:

если выступает в роли промежуточного производного класса Bear() : dance( two left feet ) {}

... остальное без изменения

М1 сделали этот конструктор защищенным, поскольку он вызывается только из производных классов. Если аналогичный конструктор по умолчанию обеспечен и для

Panda::Panda( string name, bool onExhibit=true )

: ZooAnimal( name, onExhibit, Panda ), Endangered( Endangered::environment, Endangered::critical ),

sleeping( false )

класса Raccoon, можно следующим образом модифицировать конструктор Panda:

18.5.3. Порядок вызова конструкторов и деструкторов

Виртуальные базовые классы всегда конструируются перед невиртуальными, вне зависимости от их расположения в иерархии наследования. Например, в приведенной иерархии у класса TeddyBear (плюшевый мишка) есть два виртуальных базовых: непосредственный - ToyAnimal (игрушечное животное) и экземпляр ZooAnimal, от

class Character { ... }; персонаж

class BookCharacter : public Character { ... };

/ / тературн персонаж class ToyAAnimal { ... }; игрушка

class TeddyBear : public BookCharacter,

public Bear, public virtual ToyAAnimal

которого унаследован класс Bear:

Эта иерархия изображена на рис. 18.5, где виртуальное наследование показано пунктирной стрелкой, а невиртуальное - сплошной.




BookCharacter

(eddyBear


->

невиртуальное наследование

----> виртуальное наследование

Рис. 18.5. Иерархия виртуального наследования класса TeddyBear

Непосредственные базовые классы просматриваются в порядке их объявления при поиске среди них виртуальных. В нашем примере сначала анализируется поддерево наследования BookCharacter, затем Bear и наконец ToyAnimial. Каждое поддерево обходится в глубину, т.е. поиск начинается с корневого класса и продвигается вниз. Так, для поддерева BookCharacter сначала просматривается Character, а затем BookCharacter. Для поддерева Bear - ZooAnimal, а потом Bear.

При описанном алгоритме поиска порядок вызова конструкторов виртуальных базовых классов для TeddyBear таков: ZooAnimal, потом ToyAnimal.

После того как вызваны конструкторы виртуальных базовых классов , настает черед конструкторов невиртуальных, которые вызываются в порядке объявления: BookCharacter, затем Bear. Перед выполнением конструктора BookCharacter вызывается конструктор его базового класса Character.

Если имеется объявление:

TeddyBear Paddington;

ZooAnimal(); ToyAnimal(); Character();

BookCharacter();

Bear();

виртуальн базов класс Bear непосредственна виртуальн базов класс невиртуальна базов класс BookCharacter непосредственна невиртуальна базов класс непосредственна невиртуальна базов класс

то последовательность вызова конструкторов базовых классов будет такой:

TeddyBear(); ближаий производн класс

причем за инициализацию ZooAnimal и производный класс объекта Paddington.

ToyAnimal отвечает TeddyBear - ближайший

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



1 ... 317 318 319 [ 320 ] 321 322 323 ... 395

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