//
//
class Bulk_quote : public Disc_quote {
public:
Bulk_quote() = default;
Bulk_quote(const std::string& book, double price,
std::size_t qty, double disc):
Disc_quote(book, price, qty, disc) { }
//
double net_price(std::size_t) const override;
};
У этой версии класса Bulk_quote есть Disc_quote, и Quote. У каждого объекта класса Bulk_quote есть три внутренних объекта: часть Bulk_quote (пустая), часть Disc_quote и часть Quote.
Как уже упоминалось, каждый класс контролирует инициализацию объектов своего типа. Поэтому, даже при том, что у класса Bulk_quote нет собственных переменных-членов, он предоставляет тот же конструктор на четыре аргумента, что и первоначальный класс. Новый конструктор передает свои аргументы конструктору класса Disc_quote. Этот конструктор, в свою очередь, запускает конструктор Quote(). Конструктор Quote() инициализирует переменные-члены bookNo и price объекта bulk. Когда конструктор Quote() завершает работу, начинает работу конструктор Disc_quote(), инициализирующий переменные-члены quantity и discount. Теперь возобновляет работу конструктор Bulk_quote(). Он не делает ничего и ничего не инициализирует.
Добавление класса Disc_quote в иерархию Quote является примером
Примечательно, что, несмотря на изменение иерархии наследования, код, который использует классы Bulk_quote и Quote, изменять не придется. Но после рефакторинга классов (или любых других измененный) следует перекомпилировать весь код, который использует эти классы.
Упражнение 15.15. Определите собственные версии классов Disc_quote и Bulk_quote.
Упражнение 15.16. Перепишите класс из упражнения 15.2.2 раздела 12.1.6, представляющий ограниченную стратегию скидок, так, чтобы он происходил от класса Disc_quote.
Упражнение 15.17. Попытайтесь определить объект типа Disc_quote и посмотрите, какие сообщения об ошибке выдал компилятор.
Подобно тому, как каждый класс контролирует инициализацию своих переменных-членов (см. раздел 15.2.2), каждый класс контролирует также
Как уже упоминалось, класс использует защищенные члены в тех случаях, когда желает предоставить к ним доступ из производных классов, но защитить их от общего доступа. Спецификатор доступа protected можно считать гибридом спецификаторов private и public.
• Подобно закрытым, защищенные члены недоступны пользователям класса.
• Подобно открытым, защищенные члены доступны для членов и друзей классов, производных от данного класса.
Кроме того, защищенный член имеет еще одно важное свойство.
• Производный член класса или дружественный класс может обратиться к защищенным членам базового класса только
Чтобы лучше понять это последнее правило, рассмотрим следующий пример:
class Base {
protected:
int prot_mem; //
};
class Sneaky : public Base {