Упражнение 7.5. Снабдите класс Person
операциями возвращения имени и адреса. Должны ли эти функции быть константами? Объясните свой выбор.
Авторы классов нередко определяют такие вспомогательные функции, как наши функции add()
, read()
и print()
. Хотя определяемые ими операции концептуально являются частью интерфейса класса, частью самого класса они не являются.
Мы определяем функции, не являющиеся членом класса, как любую другую функцию, т.е. ее объявление обычно отделено от определения (см. раздел 6.1.2). Функции, концептуально являющиеся частью класса, но не определенные в нем, как правило, объявляются (но не определяются) в том же заголовке, что и сам класс. Таким образом, чтобы использовать любую часть интерфейса, пользователю достаточно включить только один файл.
read()
и print()
Функции read()
и print()
выполняют ту же задачу, что и код в разделе 2.6.2, поэтому и не удивительно, что тела этих функций очень похожи на код, представленный там:
//
//
istream &read(istream &is, Sales_data &item) {
double price = 0;
is >> item.bookNo >> item.units_sold >> price;
item.revenue = price * item.units_sold;
return is;
}
ostream &print(ostream &os, const Sales_data &item) {
os << item.isbn() << " " << item.units_sold << " "
<< item.revenue << " " << item.avg_price();
return os;
}
Функция read()
читает данные из предоставленного потока в заданный объект. Функция print()
выводит содержимое предоставленного объекта в заданный поток.
В этих функциях, однако, следует обратить внимание на два момента. Во- первых, обе функции получают ссылки на соответствующие объекты классов ввода и вывода. Классы ввода и вывода — это типы, не допускающие копирования, поэтому их передача возможна только по ссылке (см. раздел 6.2.2). Кроме того, чтение и запись в поток изменяют его, поэтому обе функции получают обычные ссылки, а не ссылки на константы.
Второй заслуживающий внимания момент: функция print()
не выводит новую строку. Обычно функции вывода осуществляют минимальное форматирование. Таким образом, пользовательский код может сам решить, нужна ли новая строка.
add()
Функция add()
получает два объекта класса Sales_data
и возвращает новый объект класса Sales_data
, представляющий их сумму:
Sales_data add(const Sales_data &lhs, const Sales_data &rhs) {
Sales_data sum = lhs; //
sum.combine(rhs); //
return sum;
}
В теле функции определяется новый объект класса Sales_data
по имени sum
, предназначенный для хранения суммы двух транзакций. Инициализируем объект sum
копией объекта lhs
. По умолчанию копирование объекта класса подразумевает копирование и членов этого объекта. После копирования у членов bookNo
, units_sold
и revenue
объекта sum
будут те же значения, что и у таковых объекта lhs
. Затем происходит вызов функции combine()
, суммирующей значения переменных-членов units_sold
и revenue объектов rhs
и sum
в последний. По завершении возвращается копия объекта sum
.
Упражнение 7.6. Определите собственные версии функций add()
, read()
и print()
.
Упражнение 7.7. Перепишите программу обработки транзакций, написанной для упражнений в разделе 7.1.2, так, чтобы использовать эти новые функции.
Упражнение 7.8. Почему функция read()
определяет свой параметр типа Sales_data
как простую ссылку, а функция print()
— как ссылку на константу?
Упражнение 7.9. Добавьте в код, написанный для упражнений в разделе 7.1.2, операции чтения и вывода объектов класса Person
.
Упражнение 7.10. Что делает условие в следующем операторе if
?
if (read(read(cin, data1), data2))