|
Программирование >> Инициализация объектов класса, структура
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 - ближайший Порядок вызова копирующих конструкторов при почленной инициализации (и копирующих операторов присваивания при почленном присваивании) такой же. Гарантируется, что деструкторы вызываются в последовательности, обратной вызову конструкторов.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.003
При копировании материалов приветствуются ссылки. |