Проектировщик должен решить, следует ли выводить завершающий символ новой строки. Лучше этого не делать: поскольку операторы вывода для встроенных типов такой символ не печатают, пользователь ожидает аналогичного поведения и от операторов в других классах. Определенный нами в классе WordCount оператор вывода можно использовать вместе с любыми другими операторами:
#include iostream
#include " WordCount.h"
int main()
{
WordCount wd( " sadness" , 12 );
cout " wd:\n" wd endl;
return 0;
}
Программа печатает на терминале строки:
wd:
sadness
Оператор вывода – это бинарный оператор, который возвращает ссылку на объект класса ostream. В общем случае структура определения перегруженного оператора вывода выглядит так:
// структура перегруженного оператора вывода
ostream&
operator ( ostream& os, const ClassType &object )
{
// произвольный код для подготовки объекта
// фактическое число членов
os // ...
// возвращается объект ostream
return os;
}
Первый его аргумент – это ссылка на объект ostream, а второй – ссылка (обычно константная) на объект некоторого класса. Возвращается ссылка на ostream. Значением всегда является объект ostream, для которого оператор вызывался.
Поскольку первым аргументом является ссылка, оператор вывода должен быть определен как обычная функция, а не член класса. (Объяснение см. в разделе 15.1.) Если оператору необходим доступ к неоткрытым членам, то следует объявить его другом класса. (О друзьях говорилось в разделе 15.2.)
Пусть Location – это класс, в котором хранятся номера строки и колонки вхождения слова. Вот его определение:
#include iostream
class Location {
friend ostream& operator&&( ostream&, const Location& );
private:
short _line;
short _col;
};
ostream& operator &&( ostream& os, const Location& lc )
{
// объект Loc выводится в виде: 10,37
os " " lc._line
" ," lc._col " " ;
return os;
}
Изменим определение класса WordCount, включив в него вектор occurList объектов Location и объект word класса string:
#include vector
#include string
#include iostream
#include "Location.h"
class WordCount {
friend ostream& operator&&( ostream&, const WordCount& );
public:
WordCount() {}
WordCount( const string &word ) : _word( word ) {}
WordCount( const string &word, int ln, int col )
: _word( word ){ insert_location( ln, col ); }
string word() const { return _word; }
int occurs() const { return _occurList.size(); }
void found( int ln, int col )
{ insert_location( ln, col ); }
private:
void insert_location( int ln, int col )
{ _occurList.push_back( Location( ln, col )); }
string _word;
vector Location _occurList;
};
В классах string и Location определен оператор вывода operator(). Так выглядит измененное определение оператора вывода в WordCount:
ostream&
operator ( ostream& os, const WordCount& wd )
{
os "" wd._occurList.size() " "
wd._word endl;
int cnt = 0, onLine = 6;
vector Location ::const_iterator first =
wd._occurList.begin();
vector Location ::const_iterator last =
wd._occurList.end();
for ( ; first != last; ++first )
{
// os Location
os *first " ";
// форматирование: по 6 в строке
if ( ++cnt = onLine )
{ os "\n"; cnt = 0; }
}
return os;
}
А вот небольшая программа для тестирования нового определения класса WordCount; позиции вхождений для простоты “зашиты” в код:
int main()
{
WordCount search( "rosebud" );