Создание объекта производного класса подразумевает создание и инициализацию внутренних объектов всех его базовых классов. В случае одиночного наследования из (единого) базового класса (см. раздел 15.2.2) в списке инициализации конструктора производного класса можно передать значения только для прямых базовых классов:
//
Panda::Panda(std::string name, bool onExhibit)
: Bear(name, onExhibit, "Panda"),
Endangered(Endangered::critical) { }
// неявное применение стандартного конструктора класса Bear для
//
Panda::Panda()
: Endangered(Endangered::critical) { }
Список инициализации конструктора позволяет передать аргументы каждому из прямых базовых классов, однако порядок выполнения конструкторов (constructor order) зависит от порядка их расположения в списке наследования класса. Порядок их расположения в списке инициализации конструктора не имеет значения. Объект класса Panda
инициализируется следующим образом.
• Внутренний объект класса ZooAnimal
, самого первого базового класса иерархии класса Panda
, непосредственного базового для класса Bear
создается первым.
• Внутренний объект класса Bear
, первого непосредственного базового класса для класса Panda
, инициализируется следующим.
• Внутренний объект класса Endangered
, второго непосредственного базового класса для класса Panda
, инициализируется следующим.
• Последней инициализируется наиболее производная часть класса Panda
.
По новому стандарту производный класс может наследовать свои конструкторы от одного или нескольких своих базовых классов (см. раздел 15.7.4). Нельзя наследовать тот же конструктор (т.е. конструктор с тем же списком параметров) от более чем одного базового класса:
struct Base1 {
Base1() = default;
Base1(const std::string&);
Base1(std::shared_ptr
};
struct Base2 {
Base2() = default;
Base2(const std::string&);
Base2(int);
};
//
//
struct D1: public Base1, public Base2 {
using Base1::Base1; //
using Base2::Base2; //
};
Класс, унаследовавший тот же конструктор от нескольких базовых классов, должен определить собственную версию этого конструктора:
struct D2: public Base1, public Base2 {
using Base1::Base1; //
using Base2::Base2; //
//
D2(const string &s) : Base1(s), Base2(s) { }
D2() = default; //
//
};
Как обычно, деструктор в производном классе отвечает за освобождение ресурсов, зарезервированных этим классом. Автоматически освобождаются члены только производного класса и всех базовых классов. Тело синтезируемого деструктора пусто.
Деструкторы всегда выполняются в порядке, обратном вызову конструкторов. В данном примере порядок вызова деструкторов будет следующим: ~Panda()
, ~Endangered()
, ~Bear()
, ~ZooAnimal()
.
Как и в случае одиночного наследования, классы с несколькими базовыми классами, определяющими собственные конструкторы копирования, перемещения и операторы присвоения, должны копировать, перемещать и присваивать весь объект (см. раздел 15.7.2). Базовые части класса, производного от нескольких базовых, автоматически копируются, перемещаются и присваиваются, только если производный класс использует синтезируемые версии этих функций-членов. В синтезируемых функциях-членах управления копированием каждый базовый класс неявно создается, присваивается или удаляется с использованием соответствующего члена базового класса.