Aiman Khan
Aiman Khan

Reputation: 21

Why use std::ostream and friend for << operator overloading?

I want to overload the operator << to print a list using std::cout, for example:

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

After searching, I came to know that this can be done using ostream, but I am not sure how this is done. Like why is this necessary to take in ostream as a reference and then return it?

Operator Overloading function:

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
}

And I also don't understant why do we have to make that a friend function? If I remove the keyword friend, it gives me an error that << operator is a binary operator. I am using Xcode.

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);
};

Upvotes: 2

Views: 5585

Answers (2)

The operator << is a binary operator, meaning that it needs one operand on the left-hand side and one on the right-hand side. For example, when you write cout << "Hello World" the left-hand side operand is cout which is of type ostream and the right-hand side operand is the string "Hello World". Similarly, to overload the operator for one of your classes you must define what will be the left-hand side operand and what the right-hand side operand, just as overloading the plus (+) operator, or any other binary operator, requires you to define what are the operands. Therefore, os should be used where you have written cout, as has already been pointed out in a previous answer, and it will have the "value" cout if the left-hand side opernad is cout.

As for returning os, the reason to do this is in order to be able to chain multiple printing statements. It is possible using integers to write cout << 3 << 5;, because initially the first << operator is evaluated, printing 3, then os is returned and is passed as the left-hand side operand to the next <<. If the overloaded operator does not return os, this will be impossible to do with objects of your class.

Finally, as has already been said, the overload should be a friend of the class because it needs access to its private members, and since it is not a member function of the class, it cannot have it unless it is a friend to it.

Upvotes: 1

In the operator << overload you shouldn’t use cout, you should use the ostream you are receiving as a parameter, just change the cout for os. This is because the cout will print that output stream you are returning.

You need to make that operator overload a friend function because even though the operator isn’t a part of the class, it will have access to the class private attributes and functions, so it can access the elements and print them.

Upvotes: 3

Related Questions