3

上学期我一直在复习一些旧的硬件作业。这是一个给定的打印函数,用于打印出链表对象。我不明白为什么重载运算符需要两个参数,一个是 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;
}
4

4 回答 4

6

顺便问一下这个问题以及它有多基本,我将尝试给出一个非常简单化(尽管相当非正式且不那么迂腐)的答案。

我不明白为什么重载运算符需要两个参数,一个是 os 对象

operator<< 是二元运算符。它有左侧和右侧。当你写:

cout << 123;

您正在使用两个操作数(参数)调用此运算符:左侧为“cout”,右侧为整数“123”。

当我们在 main.cpp 上打印出实际的链表对象时,我们不需要传递 os 对象。

您的 print 函数是类的成员函数或运算符。这将隐含地推断出第一个参数,粗略地说,不需要显式传递,因为您已经拥有用于列表对象的“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, "hello"),然后它给了我们另一个 ostream 引用来使用它,然后允许我们继续调用 operator<<(cout, "world")。例如,如果它返回 void,它将不允许我们在一个语句中调用该运算符两次,因为我们会尝试以 void 作为左侧操作数输出“world”。

为什么我们不能只使用 cout 而不是 "os <<" ?

cout 基本上实现了 ostream 接口。ofstream、ostringstream 和其他类型的输出流也是如此。通过根据所需的基本接口而不是某些特定的 ostream 派生来编写它,您可以让您编写的代码与 stdio 流、文件流、流流等一起使用。基本上,它使您的代码非常通用且可重用,这是您在实用时应该努力做的事情。当您处理多态性的概念时,您将更多地了解这个主题。

于 2012-02-27T20:00:43.053 回答
2

因为它是一个全局非成员函数。对于成员函数版本,第一个参数隐含地是调用对象,this. 这意味着您的班级必须始终在左侧。对于非成员函数,它是一个显式参数;这样,您可以指定所需的任何类型,并为无法修改源的类重载运算符(只要至少一个参数是用户定义的类型)。

您使用的原因os是它适用于文件流和所有内容(继承自 的任何内容ostream),而不仅仅是cout.

它返回os,以便您可以operator<<对返回值进行更多调用。这启用了运算符链接,例如w << x << y << z,与 相同operator<<(operator<<(operator<<(w, x), y), z)。如果你返回void什么的,你将不得不停下来,w << x因为你不能对返回值做任何事情void

于 2012-02-27T19:46:59.167 回答
0

我不明白为什么重载运算符需要两个参数,一个是 os 对象。当我们在 main.cpp 上打印出实际的链表对象时,我们不需要传递 os 对象。

是的,你做到了:当你说 时cout << x,你正在传递coutxoperator<<

另外,为什么要返回os?

使成为cout << x << y可能。这被解析为(cout << x) << y,即它插入y到 的返回值中cout << x

为什么我们不能只使用 cout 而不是 "os <<" ?

因为有时您想输出到标准输出之外的另一个流。

于 2012-02-27T19:48:29.370 回答
0

当我们在 main.cpp 上打印出实际的链表对象时,我们不需要传递 os 对象。

是的,你做到了.. 类似的东西cout << obj;,其中 cout 是os输出流。

另外,为什么要返回os?为什么我们不能只使用 cout 而不是 "os <<" ?

这允许链接:cout << obj << " " << obj2;

为什么我们不能只使用 cout 而不是 "os <<" ?

这将硬连线输出流,因此您无法写入文件或任何其他输出。

于 2012-02-27T19:50:57.247 回答