Why and how to overload operator<< for printing

喜你入骨 提交于 2019-12-23 10:41:03

问题


I have written a program for implementation of stack. And I have one display function in it.

This is how I wrote display function at first:

template <class t>
void Mystack<t>::display()
{
    for (int i = 0; i <= top; i++)
    {
        std::cout << input[i] << " ";
    }
}

Then I was suggested by developers to write a display function to be more generic. So I wrote display function as:

template <class T>
void Mystack<T>::display(std::ostream &os) const         
{
    for (int i = 0; i <= top; i++)
    {
        os << input[i] << " ";
    }
}

As per my understanding the benefit of writing above function is that now I have a generic display function which I can use to display data to console or to a file too.

Question 1: Is my understanding correct?

Now another suggestion is to write function something like:

template <typename T>
friend std::ostream& operator<<(std::ostream& s, Mystack<T> const& d) {
    d.display(s);
    return s;
}

Question 2: What is the benefit of having above display function? What exactly will I be able to achieve by having above display function?


回答1:


For question 1, your understanding is correct, but the real improvement comes from question 2's suggestion of writing:

template <typename T>
friend std::ostream& operator<<(std::ostream&, Mystack<T> const& );

That will let anybody stream objects of your type in the same way they would stream anything else:

std::cout << "Hi, my stack is " << stack << ", it has size " << stack.size();

to any stream they want:

some_file << "Result of computation is: " << stack;
std::cerr << "Error, invalid stack: " << stack << ", expected: " << some_other_thing;



回答2:


Firstly - yes. By taking the std::ostream& parameter, you can output to any derived stream too, like std::ofstream, or std::cout, std::cerr.

Using operator<< allows you to, use that operator. Consider:

mystack<int> stackOfInts;
//...
std::cout << "Stack contents:" << std::endl << stackOfInts << std::endl;

It's just more idiomatic than a 'standard' function call.

Returning the stream allows the chaining of the operator, as in the above example. The chaining is effectively passing the result of a call to operator<< into another one:

operator<<( operator<<("Stack contents:", std::endl), stackOfInts ) );

If this overloaded call doesn't also return an std::ostream&, then there is no way to do:

operator<<( resultOfAbove, std::endl );

Declaring the function a friend allows its definition to use private members. Without this, you would have to do something like write a public getter for each private member.




回答3:


Both display function are basically the same. The different is the way you call the function. With first function, you call function in usual way:

std::cout<<"This is MyStack (with first method): ";
m.display(std::cout);      //function call
std::cout<<std::endl;

With second function, you call function with operator "<<":

std::cout<<"This is MyStack (with second method): "
               <<m   //function call
               <<std::endl;

But I personally prefer the second one. Since it's more familiar to me.




回答4:


As with regard to Question 2, this is the way to go if you have a base class and lots of derived classes, and want to write operator<< only once, in the base class. Then, if you declare the display() function as virtual along your class hierarchy, you can choose at runtime the correct display function. That is, if you have something like

Derived foo;
std::cout << foo;

then Base::operator<< will call the Derived::display(), because it is marked as virtual and foo is passed by reference. This is the way to go when you have a class hierarchy and don't want to overload operator<< for each derived class.

This is a common trick in avoiding code duplication. See

Making operator<< virtual?

on StackOverflow for more details.



来源:https://stackoverflow.com/questions/27871074/why-and-how-to-overload-operator-for-printing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!