Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++ для начинающих (Стенли Липпман) 3-е хххх.pdf
Скачиваний:
86
Добавлен:
30.05.2015
Размер:
5.92 Mб
Скачать

С++ для начинающих

1047

Упражнение 20.5

Прочитайте фразу “riverrun, from bend of bay to swerve of shore” сначала как последовательность из девяти строк, а затем как одну строку.

Упражнение 20.6

С помощью функций getline() и gcount() прочитайте последовательность строк из стандартного ввода и найдите самую длинную (не забудьте, что строку, прочитанную за несколько обращений к getline(), нужно считать одной).

20.4. Перегрузка оператора вывода

Если мы хотим, чтобы наш тип класса поддерживал операции ввода/вывода, то необходимо перегрузить оба соответствующих оператора. В этом разделе мы рассмотрим, как перегружается оператор вывода. (Перегрузка оператора ввода тема следующего

class WordCount { friend ostream&

operator<<( ostream&, const WordCount& );

public:

WordCount( string word, int cnt=1 ); // ...

private:

string word; int occurs;

};

ostream&

operator <<( ostream& os, const WordCount& wd )

{// формат: <счетчик> слово os << "< " << " > " > "

<<wd.word;

return os;

раздела.) Например, для класса WordCount он выглядит так:

}

Проектировщик должен решить, следует ли выводить завершающий символ новой строки. Лучше этого не делать: поскольку операторы вывода для встроенных типов такой символ не печатают, пользователь ожидает аналогичного поведения и от операторов в других классах. Определенный нами в классе WordCount оператор вывода можно

#include <iostream> #include "WordCount.h"

int main()

{

WordCount wd( "sadness", 12 ); cout << "wd:\n" << wd << endl; return 0;

использовать вместе с любыми другими операторами:

}

С++ для начинающих

1048

Программа печатает на терминале строки:

wd:

<12> 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:

С++ для начинающих

1049

#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<<(). Так выглядит

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:

}

А вот небольшая программа для тестирования нового определения класса WordCount; позиции вхождений для простоты зашитыв код:

С++ для начинающих

1050

int main()

{

WordCount search( "rosebud" );

// для простоты явно введем 8 вхождений search.found(11,3); search.found(11,8); search.found(14,2); search.found(34,6); search.found(49,7); search.found(67,5); search.found(81,2); search.found(82,3); search.found(91,4); search.found(97,8);

cout << "Вхождения: " << "\n" << search << endl;

return 0;

}

После компиляции и запуска программа выводит следующее:

Вхождения:

 

 

 

 

<10> rosebud

<14,2>

<34,6>

<49,7>

<67,5>

<11,3>

<11,8>

<81,2>

<82,3>

<91,4>

<97,8>

 

 

Полученный результат сохранен в файле output. Далее мы определим оператор ввода, с помощью которого прочитаем данные из этого файла.

Упражнение 20.7

class Date { public:

// ...

private:

int month, day, year;

Дано определение класса Date:

};

Напишите перегруженный оператор вывода даты в формате:

(a)

// полное название месяца

September 8th, 1997

(b)

9 / 8 / 97

(c)Какой формат лучше? Объясните.

(d)Должен ли оператор вывода Date быть функцией-другом? Почему?

Упражнение 20.8

Определите оператор вывода для следующего класса CheckoutRecord: