Операции и для потоков
В классах iostream операции и определены для всех встроенных типов языка Си++ и для строк (тип char*). Если мы хотим использовать такую же запись для ввода и вывода других классов, определенных в программе, для них нужно определить эти операции.
class String { public: friend ostream operator(ostream os, const String s); friend istream operator(istream is, String s); private: char* str; int length; }; ostream operator(ostream os, const String s) { os s.str; return os; } istream operator(istream is, String s) { // предполагается, что строк длиной более // 1024 байтов не будет char tmp[1024]; is tmp;
if (str != 0) { delete [] str; } length = strlen(tmp); str = new char[length + 1]; if (str == 0) { // обработка ошибок length = 0; return is; } strcpy(str, tmp); return is; }
Как показано в примере класса String, операция , во-первых, является не методом класса String, а отдельной функцией. Она и не может быть методом класса String, поскольку ее правый операнд – объект класса ostream. С точки зрения записи, она могла бы быть методом класса ostream, но тогда с добавлением нового класса приходилось бы модифицировать класс ostream, что невозможно – каждый бы модифицировал стандартные классы, поставляемые вместе с компилятором. Когда же операция реализована как отдельная функция, достаточно в каждом новом классе определить ее, и можно использовать запись:
String x; . . . cout "this is a string: " x;
Во-вторых, операция возвращает в качестве результата ссылку на поток вывода. Это позволяет использовать ее в выражениях типа приведенного выше, соединяющих несколько операций вывода в одно выражение.
Аналогично реализована операция ввода. Для класса istream она определена для всех встроенных типов языка Си++ и указателей на строку символов. Если необходимо, чтобы класс, определенный в программе, позволял ввод из потока, для него нужно определить операцию в качестве функции friend.