【问题标题】: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&lt;&lt; 调用。这启用了运算符链接,例如w &lt;&lt; x &lt;&lt; y &lt;&lt; z,与operator&lt;&lt;(operator&lt;&lt;(operator&lt;&lt;(w, x), y), z) 相同。如果你返回void 什么的,你将不得不停在w &lt;&lt; x,因为你不能对void 的返回值做任何事情。

    【讨论】:

      【解决方案3】:

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

      是的,你做到了:当你说 cout &lt;&lt; x 时,你将 coutx 传递给 operator&lt;&lt;

      还有,为什么要返回os?

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

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

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

      【讨论】:

        【解决方案4】:

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

        是的,你做到了..类似于cout &lt;&lt; obj;,其中 cout 是os 输出流。

        另外,为什么它返回操作系统?为什么我们不能只使用 cout 而不是 "os

        这允许链接:cout &lt;&lt; obj &lt;&lt; " " &lt;&lt; obj2;

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-10-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-02-10
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多