上个学期,我一直在上课。 这是打印出链表对象的给定打印功能。 我不明白为什么重载运算符需要两个参数,一个是一个 os对象。当我们在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;
}
答案 0 :(得分:6)
顺便问一下这个问题及其基本程度,我将尝试给出一个非常简单的(尽管是非正式的,不那么迂腐)的答案。
我不明白为什么重载运算符需要两个参数 一个是os对象
运营商LT;&LT;是一个二元运算符。它有左手侧和右手侧。当你写:
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&lt;&lt;(cout,“hello”)然后给我们另一个ostream引用,然后允许我们继续调用operator&lt;&lt;(cout,“world”)。例如,如果它返回void,它将不允许我们在一个语句中两次调用该运算符,因为我们试图输出带有void作为左侧操作数的“world”。
为什么我们不能只使用cout而不是“os&lt;&lt;” ?
cout基本上实现了ostream接口。 ofstream,ostringstream和其他类型的输出流也是如此。通过根据所需的基本接口编写它而不是某些特定的ostream衍生物,您可以允许您编写的代码使用stdio流,文件流,流和其他流。基本上它使您的代码非常通用和可重用,这是您在实际应该努力做的事情。在解决多态性的概念时,您将更多地了解这个主题。
答案 1 :(得分:2)
因为它是全局非成员函数。使用成员函数版本,第一个参数隐式地是调用对象this
。这意味着你的班级必须始终在左侧。使用非成员函数,它是一个显式参数;这样,您可以指定所需的任何类型,并为无法修改源的类重载运算符(只要至少一个参数是用户定义的类型)。
您使用os
的原因是它适用于文件流和所有内容(任何继承自ostream
的内容),而不仅仅是cout
。
返回os
,以便您可以对返回值执行更多operator<<
次调用。这使得操作员链接(例如w << x << y << z
)与operator<<(operator<<(operator<<(w, x), y), z)
相同。如果您返回void
或其他内容,则必须停在w << x
,因为您无法对void
的返回值执行任何操作。
答案 2 :(得分:0)
我不明白为什么重载运算符需要两个参数,一个是os对象。当我们在main.cpp上打印出实际的链表对象时,我们不需要传递一个os对象。
是的,你做了:当你说cout << x
时,你将cout
和x
传递给operator<<
。
另外,为什么要返回os?
使cout << x << y
成为可能。这被解析为(cout << x) << y
,即它将y
插入cout << x
的返回值。
为什么我们不能只使用cout而不是“os&lt;&lt;” ?
因为有时您想输出到标准输出以外的其他流。
答案 3 :(得分:0)
当我们在main.cpp上打印出实际的链表对象时,我们 不需要传递os对象。
是的,你做了...... cout << obj;
,其中cout是os
输出流。
另外,为什么它会返回os?为什么我们不能只使用cout而不是“os&lt;&lt;” ?
这允许链接:cout << obj << " " << obj2;
为什么我们不能只使用cout而不是“os&lt;&lt;” ?
这会硬连接输出流,因此您无法写入文件或任何其他输出。