Перегруженный оператор << для синтаксиса ostream - PullRequest
2 голосов
/ 27 февраля 2012

В прошлом семестре я изучал несколько старых заданий в школе. Это была заданная функция печати для печати объектов связанного списка. Я не понимаю, почему перегруженный оператор принимает два параметра, один из которых является ос объект. Когда мы печатали фактические объекты связанного списка на main.cpp, мы не делали нужно передать объект ОС. Кроме того, почему он возвращает ОС? Почему мы не можем просто использовать cout вместо "os <<"? </p>

Спасибо!

template <class T>
void List<T>::print(ostream & os) const
{
    os << "<";
    ListNode * curr = head;
    while (curr != NULL) {
        os << " " << curr->data;
        curr = curr->next;
    }
    os << " >";
}



// overloaded operator<<
template <class T>
ostream & operator<<(ostream & os, const List<T> & list)
{
    list.print(os);
    return os;
}

Ответы [ 4 ]

6 голосов
/ 28 февраля 2012

Кстати, вопрос был задан и насколько он базовый, я постараюсь дать очень упрощенный (хотя и довольно неформальный и не такой педантичный) ответ.

Я не знаюНе понятно, почему перегруженный оператор принимает два параметра, и один из них является объектом os

operator << - это бинарный оператор.Он имеет левую и правую стороны.Когда вы пишете: </p>

cout << 123;

Вы вызываете этот оператор с двумя операндами (аргументами): «cout» слева и целое число «123» справа.

Когда мы печатали фактические объекты связанного списка в main.cpp, нам не нужно было передавать объект os.

Ваша функция печати является функцией-членом или оператором класса.Это подразумевает, что первый аргумент, грубо говоря, не нужно явно передавать, поскольку у вас уже есть указатель «this» для работы с вашим объектом списка.Это не относится к операторам, не являющимся членами, поскольку у вас нет неявно выведенного объекта this для работы с левым операндом.

Когда вы пишете код, подобный этому:

my_list.print(cout);

Вы можете думать об этом как о передаче двух аргументов: «my_list» и «cout».Даже если вы не пишете это явно, у вас есть доступ к «my_list» через «this» вместе с его участниками.Это не тот случай, если вы написали функцию печати не как член, например:

template <class T>
void print(const List<T>& my_list, ostream& os);

Это также относится и к вашему оператору, который не является функцией-членом.

Кроме того, почему он возвращает os?

Возврат ссылки на ostream - это то, что позволяет нам писать операторы следующим образом:

cout << "hello " << "world";

Сначала мы вызываем operator << (cout, "Привет"), который затем дает нам другую ссылку ostream для работы с которой затем позволяет нам перейти к вызову оператора << (cout, "world").Например, если он вернул void, он не позволил бы нам дважды вызывать этот оператор в одном операторе, поскольку мы пытались бы вывести «world» с void в качестве левого операнда. </p>

Почему мы не можем просто использовать cout вместо "os <<"? </p>

cout в основном реализует интерфейс ostream.То же самое относится к выходным, потоковым и другим типам выходных потоков.Записывая его с точки зрения базового интерфейса , а не какой-то конкретной производной ostream, вы позволяете написанному коду работать с потоками stdio, потоками файлов, потоками потоков и другими.По сути, это делает ваш код очень общим и пригодным для повторного использования, и это то, к чему вы должны стремиться, когда это целесообразно.Вы узнаете об этом предмете больше, когда будете заниматься концепцией полиморфизма.

2 голосов
/ 27 февраля 2012

Потому что это глобальная функция, не являющаяся членом.В версии функции-члена первым параметром является неявно вызывающий объект this.Это означает, что ваш класс всегда должен быть с левой стороны.С функцией, не являющейся членом, это явный параметр;таким образом, вы можете указать любой тип, который вам нужен, и перегрузить операторы для классов, для которых нельзя изменить источник (если хотя бы один параметр является определяемым пользователем типом).

Причина, по которойвы используете os так, чтобы он работал с файловыми потоками и всем (всем, что наследуется от ostream), а не просто cout.

Возвращает os, чтобы вы могли сделать больше1010 * вызывает возвращаемое значение.Это включает операторную цепочку, такую ​​как w << x << y << z, которая совпадает с operator<<(operator<<(operator<<(w, x), y), z).Если вы вернете void или что-то еще, вам придется остановиться на w << x, потому что вы ничего не можете сделать с возвращаемым значением void.

0 голосов
/ 27 февраля 2012

Когда мы печатали фактические объекты связанного списка в main.cpp, нам не нужно было передавать объект os.

Да, вы сделали ... что-то вроде cout << obj;, где cout - выходной поток os.

Кроме того, почему он возвращает os?Почему мы не можем просто использовать cout вместо «os <<»? </p>

Это позволяет создавать цепочки: cout << obj << " " << obj2;

Почему можно 't мы просто используем cout вместо «os <<»? </p>

Это жестко связывает выходной поток, поэтому вы не можете записать в файл или любой другой вывод.

0 голосов
/ 27 февраля 2012

Я не понимаю, почему перегруженный оператор принимает два параметра, один из которых является объектом os.Когда мы печатали фактические объекты связанного списка в main.cpp, нам не нужно было передавать объект os.

Да, вы сделали: когда вы говорите cout << x, вы передаете cout и x до operator<<.

Кроме того, почему он возвращает ОС?

Чтобы сделать возможным cout << x << y.Он анализируется как (cout << x) << y, то есть он вставляет y в возвращаемое значение cout << x.

Почему мы не можем просто использовать cout вместо "os <<"? </p>

Потому что иногда вы хотите выводить в другой поток, чем стандартный вывод.

...