Кстати, вопрос был задан и насколько он базовый, я постараюсь дать очень упрощенный (хотя и довольно неформальный и не такой педантичный) ответ.
Я не знаюНе понятно, почему перегруженный оператор принимает два параметра, и один из них является объектом 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, потоками файлов, потоками потоков и другими.По сути, это делает ваш код очень общим и пригодным для повторного использования, и это то, к чему вы должны стремиться, когда это целесообразно.Вы узнаете об этом предмете больше, когда будете заниматься концепцией полиморфизма.