3

I would really appreciate if someone could explain to me the difference between overloading the input/output operators, for example:

friend ostream& operator<<(ostream& ost, const myClass& obj) {
    return ost << obj.x << obj.y;
}

and Output/Input functions like these:

void Output(ostream& ost) {
    ost << x << y;
}

What are they used for, examples etc. Everything is acceptable. Thanks!

Jørgen Fogh
  • 7,516
  • 2
  • 36
  • 46
hopittyhop
  • 119
  • 12
  • Not much different really. The `operator<<` is called when you write `ost << obj`. That's about it - it creates a nicer(?) syntax and enables chaining, so you can output more than one thing at a time. – Bo Persson Oct 28 '15 at 14:36

4 Answers4

4

Overloading the << operator will allow you to chain output operations:

myClass a, b;

...

cout << a << ' ' << b;

Using your alternate implementation, you would have to write:

myClass a, b;

...

a.Output(cout);
cout << ' ';
a.Output(b);

The first version makes it easier to quickly see how the output will be formatted. It is also the standard way to use streams in C++.

Jørgen Fogh
  • 7,516
  • 2
  • 36
  • 46
4

The main difference is that if you overload "stream operators" then your classes can be used by template functions.

Using a standard-named output method would have worked similarly but using the stream operator has the added advantage that it can be defined for non-class types too (i.e. you can define what it means to output an integer to a stream, but you cannot define the method .output for an integer).

6502
  • 112,025
  • 15
  • 165
  • 265
3

The operator<< is used if you want to call it thus: cout << myObject ...and Output there can be used if you wanted to call it thus: myObject.Output(cout); (but, who would?).

But I suspect what you've got going on here is two competing ways of writing the << operator.

The first is the one above, with the friend keyword.

Here's another version:

void myClass::Output (ostream& ost)
{
    ost << x << y;
}

ostream& operator<<(ostream& ost, const myClass& obj) 
{
    obj.Output (ost); return ost;
}

The second version is generally considered better, because it avoids the use of friend, which is considered a security risk. Allowing non-member functions to access the private section (so the reasoning goes) reduces the security of that private section.

Here's a stack overflow article that discusses this at greater length: Should operator<< be implemented as a friend or as a member function?

...and the general philosophy of "when to use friend" is discussed here: https://softwareengineering.stackexchange.com/questions/105766/c-to-friend-or-not-to-friend

My take on this is that it is not evil to use friend, but I avoid it when it's not needed. And here, it is not, as the second version shows.

Community
  • 1
  • 1
Topological Sort
  • 2,733
  • 2
  • 27
  • 54
1

There is really no difference (from technical standpoint) between overloading any of those. As a matter of fact, even those are not special. They are simply overloadable operators - shift-left operator and shift-right operator. The reason to overload operators in general is to provide a better syntax, and the reason to overload those in particular is somewhat traditional based on perceived intuitivity.

Tradionally, operator << is overloaded to send something into something else (and called insertion operator), and operator >> is overload to extract something from something else - and is referred to as extraction operator. In majority of cases, this something you are sending to is output stream, such as std::cout, and something you are extracting from is input stream, something like std::cin. Having this in mind, std::cout << "Hello\n" is easily understood as sending string "Hello\n" to output stream, which in case of std::cout usually has an effect of printing it on the console window.

However, one could absolutely swap those overloads, and overload >> as an insertion operator. In latter case, printing would take form of std::cout >> "Hello\n". Wouldn't make any difference from compiler standpoint, but is less intuitive for programmers - those >> and << do resemble arrows.

Completely different operators could be chosen for this purpose. For instance, -> is an overloadable operator too, and choosing it as an extraction operator would be great. Just consider this: std::cin -> str. Arrow is even more explicit. Unfortunately, there is no overloadable operator <-, so this lacks symmetry.

Also, one have to remember, that operator overloading was invented to allow C++ programms define new entities without introducing new reserved language constructs. If C++ was a completely fresh language, and would not stand on the shoulders of C, the end result would likely be very different.

SergeyA
  • 61,605
  • 5
  • 78
  • 137