//
//
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 {