【问题标题】:Overloaded operator<< for ostream syntaxostream 语法的重载运算符<<
【发布时间】:2012-03-17 06:57:06
【问题描述】:
上学期我一直在复习一些旧的硬件作业。
这是一个给定的打印函数,用于打印出链表对象。
我不明白为什么重载运算符需要两个参数,一个是
操作系统对象。当我们在 main.cpp 上打印出实际的链表对象时,我们没有
需要传递一个 os 对象。另外,为什么要返回os?为什么我们不能只使用 cout
而不是 "os
谢谢!
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;
}
【问题讨论】:
标签:
c++
operator-overloading
ostream
【解决方案1】:
顺便问一下问题的基本原理,我将尝试给出一个非常简单(尽管相当非正式且不那么迂腐)的答案。
我不明白为什么重载的运算符需要两个参数
一个是 os 对象
operator
cout << 123;
您正在使用两个操作数(参数)调用此运算符:左侧为“cout”,右侧为整数“123”。
当我们在 main.cpp 上打印出实际的链表对象时,我们
不需要传递 os 对象。
您的打印函数是一个类的成员函数或运算符。这将隐含地推断出第一个参数,粗略地说,不需要显式传递,因为您已经拥有用于列表对象的“this”指针。非成员运算符并非如此,因为您没有隐式推导的“this”对象可用于左侧操作数。
当你编写这样的代码时:
my_list.print(cout);
您可以将其视为实际上传递了两个参数,“my_list”和“cout”。即使您没有明确编写它,您也可以通过“this”及其成员访问“my_list”。如果您将 print 函数编写为非成员,则情况并非如此,如下所示:
template <class T>
void print(const List<T>& my_list, ostream& os);
这也是你的操作符不是成员函数的情况。
还有,为什么要返回os?
返回对 ostream 的引用允许我们编写如下语句:
cout << "hello " << "world";
首先我们调用operator
为什么我们不能只使用 cout 而不是 "os
cout 基本上实现了 ostream 接口。 ofstream、ostringstream 和其他类型的输出流也是如此。通过根据所需的基本接口而不是某些特定的 ostream 派生来编写它,您可以让您编写的代码与 stdio 流、文件流、流流等一起使用。基本上它使您的代码非常通用且可重用,这是您在实际时应该努力做的事情。随着您处理多态性的概念,您将更多地了解这个主题。
【解决方案2】:
因为它是一个全局非成员函数。对于成员函数版本,第一个参数隐含地是调用对象this。这意味着您的班级必须始终在左侧。对于非成员函数,它是一个显式参数;这样,您可以指定任何您想要的类型,并为您无法修改源的类重载运算符(只要至少一个参数是用户定义的类型)。
您使用os 的原因是它适用于文件流和所有内容(继承自ostream 的任何内容),而不仅仅是cout。
它返回os,以便您可以对返回值进行更多operator<< 调用。这启用了运算符链接,例如w << x << y << z,与operator<<(operator<<(operator<<(w, x), y), z) 相同。如果你返回void 什么的,你将不得不停在w << x,因为你不能对void 的返回值做任何事情。
【解决方案3】:
我不明白为什么重载的运算符需要两个参数,一个是 os 对象。当我们在 main.cpp 上打印出实际的链表对象时,我们不需要传递 os 对象。
是的,你做到了:当你说 cout << x 时,你将 cout 和 x 传递给 operator<<。
还有,为什么要返回os?
使cout << x << y 成为可能。这被解析为(cout << x) << y,即将y插入到cout << x的返回值中。
为什么我们不能只使用 cout 而不是 "os
因为有时您希望输出到标准输出之外的另一个流。
【解决方案4】:
当我们在 main.cpp 上打印出实际的链表对象时,我们
不需要传递 os 对象。
是的,你做到了..类似于cout << obj;,其中 cout 是os 输出流。
另外,为什么它返回操作系统?为什么我们不能只使用 cout 而不是 "os
这允许链接:cout << obj << " " << obj2;
为什么我们不能只使用 cout 而不是 "os
这将硬连线输出流,因此您无法写入文件或任何其他输出。