Каждый класс наследует все члены своего прямого базового класса. Большинство производных классов наследует члены своего прямого базового класса. Члены прямого базового класса включают унаследованные из его базового класса и т.д. по цепи наследования. Фактически самый последний производный объект содержит часть его прямого базового класса и каждого из его косвенных базовых классов.
final
:
class NoDerived final { /* */ }; //
//
class Base { /* */ };
//
class Last final : Base { /* */ }; //
class Bad : NoDerived { /* */ }; //
class Bad2 : Last { /* */ }; //
Упражнение 15.4. Какие из следующих объявлений (если они есть) некорректны? Объясните, почему.
class Base { ... };
(a) class Derived : public Derived { ... };
(b) class Derived : private Base { ... };
(c) class Derived : public Base;
Упражнение 15.5. Напишите собственную версию класса Bulk_quote
.
Упражнение 15.6. Проверьте свою функцию print_total()
из упражнения раздела 15.2.1, передав ей объекты класса Quote
и Bulk_quote
.
Упражнение 15.7. Определите класс, реализующий ограниченную стратегию скидок, которая применяет скидку только к покупкам до заданного предела. Если количество экземпляров превышает этот предел, к остальным применяется обычная цена.
Обычно ссылку или указатель можно связать только с тем объектом, тип которого либо совпадает с типом ссылки или указателя (см. раздел 2.3.1 и раздел 2.3.2), либо допускает константное преобразование в него (см. раздел 4.11.2). Классы, связанные наследованием, являются важным исключением: с объектом производного типа можно связать указатель или ссылку на тип базового класса. Например, ссылку Quote&
можно использовать для обращения к объекту Bulk_quote
, а адрес объекта Bulk_quote
можно сохранить в указателе Quote*
.
У факта возможности привязки ссылки (или указателя) на тип базового класса к объекту производного есть очень важное следствие: при использовании ссылки (или указателя) на тип базового класса неизвестен фактический тип объекта, с которым он связан. Этот объект может быть как объектом базового класса, так и производного.
При использовании связанных наследованием типов нередко приходится отличать
Рассмотрим пример, когда функция print_total()
вызывает функцию net_price()
(см. раздел 15.1):
double ret = item.net_price(n);
Известно, что статическим типом параметра item
является Quote&
. Динамический тип зависит от типа аргумента, с которым связан параметр item
. Этот тип не может быть известен, пока не произойдет вызов во время выполнения. Если функции print_total()
передать объект класса Bulk_quote
, то статический тип параметра item
будет отличаться от его динамического типа. Как уже упоминалось, статический тип параметра item
— это Quote&
, но в данном случае динамическим типом будет Bulk_quote
.