Why and how to overload the << operator to print

I wrote a program to implement the stack. And I have one display function.

This is how I first wrote the display function:

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

Then the developers were asked to write a mapping function more general. Therefore, I wrote a 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 I understand it, the advantage of writing the above function is that I now have a general display function that I can use to display data in the console or in a file.

Question 1 : Do I understand correctly?

Now another suggestion is to write a 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 advantage of the display function above? What exactly can I achieve with the display function above?

+5
source share
4 answers

To question 1, your understanding is correct, but the real improvement comes from sentence 2 of the writing question:

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

This will allow someone to pass objects of your type in the same way that they will pass anything else:

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

for any stream they want:

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

Firstly, yes. By accepting the std::ostream& parameter, you can also output to any derived stream, for example std::ofstream or std::cout , std::cerr .

Using operator<< , you can use this operator. Consider:

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

This is simply more idiomatic than a โ€œstandardโ€ function call.

Returning a stream allows you to bind an operator, as in the above example. The chain effectively passes the result of calling operator<< to another:

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

If this overloaded call also does not return std::ostream& , then there is no way to do:

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

Declaring a friend function allows its definition to use private members. Without this, you will have to do something like writing a public recipient for each private member.

+5
source

Both display functions are basically the same. Another is how you call the function. With the first function, you call the function in the usual way:

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

In the second function, you call the function with the "<" operator:

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

But I personally prefer the second. Since he is more familiar to me.

+1
source

As with Question 2 , this is the way to go if you have a base class and many 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 the correct display function at runtime. That is, if you have something like

 Derived foo; std::cout << foo; 

then Base::operator<< will call 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 you don't want to overload operator<< for each derived class.

This is a common trick to avoid code duplication. Cm

Create operator <<virtual?

at StackOverflow for more details.

0
source

Source: https://habr.com/ru/post/1210774/


All Articles