Урок 133. Перегрузка операторов ввода и вывода

   ⁄ 

 Обновлено 10 Апр 2018  ⁄ 

⁄   184

Для классов с множеством переменных-членов, выводить в консоль каждую переменную отдельно может быть несколько утомительно. Например, рассмотрим следующий класс:

Если вы захотите вывести объект этого класса на экран, то вам нужно будет сделать что-то следующее:

Конечно, было бы проще написать отдельную функцию вывода, которую можно было бы повторно использовать. Например, функцию print():

Теперь уже намного лучше, но здесь также есть свои нюансы. Поскольку print() возвращает void, то эту функцию нельзя вызывать в середине стейтмента вывода. Вместо этого стейтмент вывода придется разбить на несколько частей (строк):

А вот если бы мы могли просто написать:

и получить тот же результат. Без необходимости разбивать стейтмент вывода на несколько строк и помнить название функции вывода.

К счастью, это можно сделать, перегрузив оператор <<.

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

Перегрузка оператора вывода << аналогична перегрузке оператора + (оба являются бинарными операторами), за исключением того, что их типы различны.

Рассмотрим выражение std::cout << point. Если оператором является <<, то что тогда операнды? Левым операндом является объект std::cout, а правым — объект нашего класса Point. std::cout фактически является объектом типа std::ostream. Поэтому перегрузка оператора << выглядит следующим образом:

Реализация перегрузки оператора << для нашего класса Point довольно проста – так как C++ уже знает, как выводить значения типа double, а все наши переменные-члены являются типа double, то мы можем просто использовать оператор << для вывода переменных-членов нашего Point. Вот класс Point, что выше, но уже с перегруженным оператором <<:

Всё довольно просто — обратите внимание, насколько проще стал стейтмент вывода по сравнению с другими стейментами из примеров выше. Наиболее заметным отличием является то, что std::cout стал параметром out в нашей функции перегрузки (который затем станет ссылкой на std::cout при вызове этого оператора).

Самое интересное здесь — тип возврата. С перегрузкой арифметических операторов мы вычисляли и возвращали результат по значению. Однако, если вы попытаетесь возвратить std::ostream по значению, то получите ошибку компилятора. Это случится из-за того, что std::ostream запрещает свое копирование.

В этом случае мы возвращаем левый параметр в качестве ссылки. Это не только предотвращает создание копии std::ostream, но также позволяет нам «связать» стейтменты вывода вместе, например std::cout << point << std::endl;.



Вы могли бы подумать, что, поскольку оператор << не возвращает значение обратно в caller, то мы должны были бы указать тип возврата void. Но подумайте, что произойдет, если наш оператор << будет возвращать void. Когда компилятор обрабатывает std::cout << point << std::endl;, то, учитывая правила приоритета/ассоциативности, он будет обрабатывать это выражение как (std::cout << point) << std::endl;. Тогда std::cout << point приведет к вызову функции перегрузки оператора <<, которая возвратит void, и вторая часть выражения будет обрабатываться как void << std::endl; — в этом нет смысла!

Возвращая параметр out в качестве возвращаемого значения выражения (std::cout << point) мы возвращаем std::cout и вторая часть нашего выражения обрабатывается как std::cout << std::endl; — вот где сила!

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

Результат:

Point(3, 4.7, 5) Point(9, 10.5, 11)

Перегрузка оператора ввода >>

Также можно перегрузить и оператор ввода. Всё почти также, как и с оператором вывода, но главное, что нужно помнить — std::cin является объектом типа std::istream. Вот наш класс Point с перегруженным оператором ввода >>:

Вот пример программы с использованием как перегруженного оператора <<, так и >>:

Предположим, что пользователь введет 4.0, 5.5 и 8.37, тогда результат программы:

You entered: Point(4, 5.5, 8.37)

Итого

Перегрузка операторов << и >> намного упрощают процесс вывода класса на экран и получение пользовательского ввода с записью в класс.

Тест

Используя класс Fraction ниже, добавьте перегрузку операторов << и >>.

Следующий фрагмент кода:

должен производить следующий результат:

Enter fraction 1: 3/4
Enter fraction 2: 4/9
3/4 * 4/9 is 1/3

Вот класс Fraction:

Ответ



Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (1 оценок, среднее: 5,00 из 5)
Загрузка...
Подписаться на обновления:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

ПОДПИСЫВАЙТЕСЬ

НА КАНАЛ RAVESLI В TELEGRAM

@ravesli

ПОДПИСАТЬСЯ БЕСПЛАТНО