【问题标题】:Why use std::ostream and friend for << operator overloading?为什么要使用 std::ostream 和朋友进行 << 运算符重载?
【发布时间】:2017-10-17 15:15:00
【问题描述】:

我想重载运算符

std::cout << list 
//ouputs as {1,2,3,..}

经过搜索,我知道可以使用ostream来完成,但我不确定这是如何完成的。比如为什么需要将 ostream 作为参考然后返回呢?

运算符重载功能:

ostream& operator<<(ostream& os, List list) 
{
    Node* temp = list.start; //points to the start of the list
    cout<<"{";
    while(temp)
    {
        cout << temp->data; //cout all the data
        if (temp->next != NULL)
            cout << ",";
        temp = temp->next;
    }
    cout<<"}" << endl;
    return os; //returns the ostream
}

而且我也不明白为什么我们必须将其设为朋友功能?如果我删除关键字朋友,它会给我一个错误,即

List.hpp

class List
{
    Node* start;
public:
    List();
    ~List();
    void emptyList();
    void append(int);
    void insert(int, int);
    void print();
    int  length();
    void remove_at(int);
    int get_value_index(int);
    int get_value_at(int);
    List operator-(int); 
    friend ostream& operator<<(ostream& os,List); //why friend function??
    List operator=(List);
    List operator+(int);
    List operator+(List);
    int& operator[](const int ind);
    bool operator==(List);
};

【问题讨论】:

  • 这里的讨论中涵盖了方法和原因:stackoverflow.com/q/2828280/1531971
  • 从 cout << 42 << mylist << "yo"
  • 只是为了澄清一下:您可以在您的class List 中定义void operator&gt;&gt;(ostream&amp; os);,并将其称为list &gt;&gt; cout;。不推荐,只是为了说明。

标签: c++


【解决方案1】:

在运算符cout更改为os。这是因为 cout 将打印您返回的输出流。

您需要使该运算符重载友元函数,因为即使该运算符不是类的一部分,它也可以访问类的私有属性和函数,因此它可以访问元素并打印它们。

【讨论】:

  • 要清楚。如果您能够在不访问私有方法或数据的情况下将您的类转换为可打印的字符串,则不需要friend。避免friend 的一种有用方法是在类上定义公共toString() 方法并实现为os &lt;&lt; list.toStringIO;
【解决方案2】:

运算符&lt;&lt; 是二元运算符,这意味着它需要左侧一个操作数,右侧一个操作数。例如,当您编写cout &lt;&lt; "Hello World" 时,左侧操作数是cout,其类型为ostream,右侧操作数是字符串"Hello World"。同样,要为您的一个类重载运算符,您必须定义左侧操作数和右侧操作数,就像重载加号 (+) 运算符或任何其他二元运算符一样,需要您定义什么是操作数。因此,os 应该用在你写了cout 的地方,正如在前面的答案中已经指出的那样,如果左侧操作符是cout,它将具有“值”cout

至于返回os,这样做的原因是为了能够链接多个打印语句。可以使用整数写入cout &lt;&lt; 3 &lt;&lt; 5;,因为最初会评估第一个&lt;&lt; 运算符,打印3,然后返回os 并作为左侧操作数传递给下一个&lt;&lt;。如果重载的操作符没有返回os,那么你的类的对象就不可能做到这一点。

最后,正如已经说过的,重载应该是类的友元,因为它需要访问它的私有成员,并且由于它不是类的成员函数,除非它是友元,否则它不能拥有它给它。

【讨论】:

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