>totalRevenue
соответственно. Выводим эти значения, а затем проверяем, были ли книги проданы, и если да, то выводим вычисленную среднюю цену за книгу. Если никаких продаж не было, выводим сообщение, обращающее внимание на этот факт.Упражнение 2.41. Используйте класс >Sales_data
для перезаписи кода упражнений из разделов 1.5.1, 1.5.2 и 1.6. А также определите свой класс >Sales_data
в том же файле, что и функция >main()
.
Как будет продемонстрировано в разделе 19.7, класс можно определить в функции, однако такие классы ограничены по функциональным возможностям. Поэтому классы обычно не определяют в функциях. При определении класса за пределами функции в каждом файле исходного кода может быть только одно определение этого класса. Кроме того, если класс используется в нескольких разных файлах, определение класса в каждом файле должно быть тем же.
Чтобы гарантировать совпадение определений класса в каждом файле, классы обычно определяют в файлах заголовка. Как правило, классы хранятся в заголовках, имя которых совпадает с именем класса. Например, библиотечный тип >string
определен в заголовке >string
. Точно так же, как уже было продемонстрировано, наш класс >Sales_data
определен в файле заголовка >Sales_data.h
.
Заголовки (обычно) содержат сущности (такие как определения класса или переменных >const
и >constexpr
(см. раздел 2.4), которые могут быть определены в любом файле только однажды. Однако заголовки нередко должны использовать средства из других заголовков. Например, поскольку у класса >Sales_data
есть член типа >string
, заголовок >Sales_data.h
должен включать заголовок >string
. Как уже упоминалось, программы, использующие класс >Sales_data
, должны также включать заголовок >string
, чтобы использовать член >bookNo
. В результате использующие класс >Sales_data
программы будут включать заголовок >string
дважды: один раз непосредственно и один раз как следствие включения заголовка >Sales_data.h
. Поскольку заголовок мог бы быть включен несколько раз, код необходимо писать так, чтобы обезопасить от многократного включения.
Наиболее распространенный способ обезопасить заголовок от многократного включения подразумевает использование препроцессора. Препроцессор (preprocessor), унаследованный языком С++ от языка С, является программой, которая запускается перед компилятором и изменяет исходный текст программ. Наши программы уже полагаются на такое средство препроцессора, как директива >#include
. Когда препроцессор встречает директиву >#include
, он заменяет ее содержимым указанного заголовка.
Программы С++ используют также препроцессор для защиты заголовка (header guard). Защита заголовка полагается на переменные препроцессора (см. раздел 2.3.2). Переменные препроцессора способны находиться в одном из двух состояний: она либо определена, либо не определена. Директива