Операторы ввода и вывода, соответствующие соглашениям библиотеки iostream, должны быть обычными функциям, а не членами класса. Эти операторы не могут быть членами нашего класса. Если бы это было так, то левый операнд должен был быть объектом типа нашего класса:

Sales_data data;

data << cout; // если бы оператор operator<<

              // был членом класса Sales_data

Если бы эти операторы были членами некоего класса, то они должны были бы быть членами класса istream или ostream. Но эти классы являются частью стандартной библиотеки, а добавлять члены в библиотечные классы нельзя.

Таким образом, если необходимо определить операторы ввода-вывода для собственного типа, их следует определить как функции, не являющиеся членами класса. Конечно, операторы ввода-вывода обычно должны читать или выводить данные не открытых переменных-членов. Как следствие, операторы ввода-вывода обычно объявляют дружественными (см. раздел 7.2.1).

Упражнения раздела 14.2.1

Упражнение 14.6. Определите оператор вывода для класса Sales_data.

Упражнение 14.7. Определите оператор вывода для класса String, написанного для упражнений раздела 13.5.

Упражнение 14.8. Определите оператор вывода для класса, который был выбран в упражнении 7.40 раздела 7.5.1.

<p><image l:href="#reader.png"/>14.2.2. Перегрузка оператора ввода <code>>></code></p>

Обычно первый параметр оператора ввода является ссылкой на поток, из которого осуществляется чтение, а второй параметр — ссылкой на некий неконстантный объект, в который предстоит прочитать данные. Обычно оператор возвращает ссылку на свой поток. Второй параметр не должен быть константным потому, что задачей оператора ввода и является собственно запись данных в этот объект.

Оператор ввода класса Sales_data

В качестве примера напишем оператор ввода для класса Sales_data:

istream &operator>>(istream &is, Sales_data &item) {

 double price; // инициализировать не нужно; читать в price

               // прежде, чем использовать

 is >> item.bookNo >> item.units_sold >> price;

 if (is) // проверить успех ввода данных

  item.revenue = item.units_sold * price;

 else

  item = Sales_data(); // ввод неудачен: вернуть объект в

                       // стандартное состояние

 return is;

}

За исключением оператора if это определение подобно прежней функции read() (см. раздел 7.1.3). Оператор if проверяет, было ли чтение успешно. Если произойдет ошибка ввода-вывода, он вернет объект Sales_data в состояние пустого объекта. Это гарантирует корректность состояния объекта.

Операторы ввода должны учитывать возможность неудачи ввода, а операторы вывода об этом могут не заботиться.

Ошибки во время ввода

В операторе ввода возможны следующие ошибки.

• Операция чтения может потерпеть неудачу из-за наличия в потоке данных неподходящего типа. Например, после чтения переменной-члена bookNo оператор ввода подразумевает, что следующие два элемента будут числовыми данными. Если во вводе окажутся не числовые данные, поток будет недопустим и все последующее попытки чтения из него потерпят неудачу.

• Во время любой из операций чтения может встретиться конец файла или произойти другая ошибка потока ввода.

Чтобы не проверять каждую часть прочитанных данных, можно проверить состояние потока в целом и только потом использовать прочитанные данные

if (is) // проверить успех ввода данных

 item.revenue = item.units_sold * price;

else

 item = Sales_data(); // ввод неудачен: вернуть объект в

                      // стандартное состояние

При сбое любой из операций чтения значение переменной-члена price останется неопределенным. Следовательно, перед ее использованием следует проверить, допустим ли еще поток ввода. Если это так, осуществляется вычисление значения переменной revenue. В случае ошибки ничего страшного не произойдет, поскольку будет возвращен пустой объект класса Sales_data. Для этого объекту item присваивается новый объект класса Sales_data, созданный при помощи стандартного конструктора. После этого присвоения переменная-член bookNo объекта item будет содержать пустую строку, а его переменные члены revenue и units_sold — нулевое значение.

Перейти на страницу:

Похожие книги