Каждый класс наследует все члены своего прямого базового класса. Большинство производных классов наследует члены своего прямого базового класса. Члены прямого базового класса включают унаследованные из его базового класса и т.д. по цепи наследования. Фактически самый последний производный объект содержит часть его прямого базового класса и каждого из его косвенных базовых классов.
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.