С++ для начинающих

       

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


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

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

class BookCharacter : public Character { ... };

                                 // литературный персонаж

class ToyAnimal { ... };         // игрушка

class TeddyBear : public BookCharacter,

                  public Bear, public virtual ToyAnimal

                  { ... };

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

Character                               ZooAnimal                               ToyAnimal

BookCharacter                               Bear

TeddyBear

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

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

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

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

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

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

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

TeddyBear Paddington;

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

ZooAnimal();          // виртуальный базовый класс Bear

ToyAnimal();          // непосредственный виртуальный базовый класс

Character();          // невиртуальный базовый класс BookCharacter

BookCharacter();      // непосредственный невиртуальный базовый класс

Bear();               // непосредственный невиртуальный базовый класс

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

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

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



Содержание раздела