где
— имя производного класса;
— имя базового класса;
— список параметров конструктора;
передают параметры из конструктора производного класса в конструктор базового. В классе Bulk_quote
унаследованный конструктор был бы эквивалентен следующему:
Bulk_quote(const std::string& book, double price,
std::size_t qty, double disc):
Disc_quote(book, price, qty, disc) { }
Если у производного класса есть какие-нибудь собственные переменные-члены, они инициализируются по умолчанию (см. раздел 7.1.4).
В отличие от объявлений using
для обычных членов, объявление using
для конструктора не изменяет уровень доступа унаследованного конструктора (конструкторов). Например, независимо от того, где расположено объявление using
, закрытый конструктор в базовом классе остается закрытым в производном; то же относится к защищенным и открытым конструкторам.
Кроме того, объявление using
не может использовать определение как explicit
или constexpr
. Если конструктор объявлен как explicit
(см. раздел 7.5.4) или constexpr
(см. раздел 7.5.6) в базовом классе, у унаследованного конструктора будет то же свойство.
Если у конструктора базового класса есть аргументы по умолчанию (см. раздел 6.5.1), они не наследуются. Вместо этого производный класс получает несколько унаследованных конструкторов, в которых каждый параметр с аргументом по умолчанию благополучно пропущен. Например, если у базового класса будет конструктор с двумя параметрами, у второго из которых будет аргумент по умолчанию, то производный класс получит два конструктора: один с обоими параметрами (и никакого аргумента по умолчанию) и второй конструктор с одним параметром, соответствующим левому параметру без аргумента по умолчанию в базовом классе.
Если у базового класса есть несколько конструкторов, то за двумя исключениями производный класс унаследует каждый из конструкторов своего базового класса. Первое исключение — производный класс может унаследовать некоторые конструкторы и определить собственные версии других конструкторов. Если производный класс определяет конструктор с теми же параметрами, что и конструктор в базовом классе, то этот конструктор не наследуется. Конструктор, определенный в производном классе, используется вместо унаследованного конструктора.
Второе исключение — стандартный конструктор, конструктор копий и конструктор перемещения не наследуются. Эти конструкторы синтезируются с использованием обычных правил. Унаследованный конструктор не рассматривается как пользовательский конструктор. Поэтому у класса, который содержит только унаследованные конструкторы, будет синтезируемый стандартный конструктор.
Упражнение 15.27. Переопределите свой класс Bulk_quote
так, чтобы унаследовать его конструкторы.
При использовании контейнера для хранения объектов из иерархии наследования их обычно хранят косвенно. Нельзя поместить объекты связанных наследованием типов непосредственно в контейнер, поскольку нет никакого способа определить контейнер, содержащий элементы разных типов.
В качестве примера определим вектор, содержащий несколько объектов для книг, которые клиент желает купать. Вполне очевидно, что не получится использовать вектор, содержащий объекты класса Bulk_quote
. Нельзя преобразовать объекты класса Quote
в объекты класса Bulk_quote
(см. раздел 15.2.3), поэтому объекты класса Quote
в этот вектор поместить не получится.
Может быть и не так очевидно, но вектор объектов типа Quote
также нельзя использовать. В данном случае можно поместить объекты класса Bulk_quote
в контейнер, но эти объекты перестанут быть объектами класса Bulk_quote
:
vector
basket;
basket.push_back(Quote("0-2 01-82 4 7 0-1", 50));
//
basket.push_back(Bulk_quote("0-201-54848-8", 50, 10, .25));
//
cout << basket.back().net_price(15) << endl;
Элементами вектора basket
являются объекты класса Quote
. Когда в вектор добавляется объект класса Bulk_quote
, его производная часть игнорируется (см. раздел 15.2.3).