KWJ2104
KWJ2104

Reputation: 2009

Operator Overloading C++ - Overloading the output "<<" operator

I'm just beginning to learn basic C++ syntax and I'm slightly confused on a piece of code I came across.

For a class created called MyString, there was an operator overloading defined as:

ostream& operator<<(ostream& os, const MyString& s)
{
    os << s.data;
    return os;
}

Then in some driver function the statement:

cout << s3 << endl;

Is ran, where s3 is of object type MyString. The result prints out the value of s3.

I don't quite understand how this statement functions. After messing with it it seems like a copy constructor is called once and then 3 objects are deconstructed. How exactly does this line work? It seems like the operator accepts a reference to an ostream and MyString, but isn't endl neither? Also why would there only be 1 copy constructor called when there are two instances of the "<<" used? Maybe I'm not even asking the right questions or my questions don't even make sense because I feel really confused about what is going on in these lines. If that is the case, can someone please expound on just a general explaination of what is going on?

Upvotes: 3

Views: 1809

Answers (5)

Ghita
Ghita

Reputation: 4505

Rules of the language says that if a non member function (operator<< is a non-member function of class MyString) is defined in the same namespace as MyString than this non member function can be chosen by the compiler to resolve that call (as explained by one of the respondents) I do not use here the standard terminology, if anybody has a more accurate description of this principle please let us know.

Upvotes: 0

CapelliC
CapelliC

Reputation: 60034

I guess the copy constructor could be generated by your compiler for cout. A stream is a rather complex object, but the choice of c++ is to provide such syntax sugar (like inline constructors) to abstract some detail. The other answers already pointed out the essential point that using references no copy is performed for parameter passing.

Upvotes: 0

AJG85
AJG85

Reputation: 16217

You can break it down a bit:

cout // this is the ostream your inserting to (stdout)
  << s3 // this calls your defined operator that writes s.data
  << endl; // this calls the operator<< for std::endl

ostream& operator<<(ostream& os, const MyString& s)
{
    // here os is the ostream (stdout) you're using via cout
    // s is s3 that you passed in
    os << s.data; // this calls operator<< for data
    return os; // this returns the reference so the subsequent call to << endl can append to the stream
}

Upvotes: 1

Seth Carnegie
Seth Carnegie

Reputation: 75150

This is a very general question, but I'll try to clear up your misunderstandings.

When you say ostream& operator<<(ostream& os, const MyString& s) { ... }, you're just defining a function that takes an ostream& as the first parameter and a const Mystring& as the second parameter, and returning an ostream&. The function happens to be named operator<< and can be called by the shorthand syntax x << y to call operator<<(x, y).

When you do cout << s3 << endl;, it is the same as doing operator<<(operator<<(cout, s3), endl);.

Neither the copy constructor nor the destructor for MyString is being called from this code. The messages you are seeing are from somewhere else.

Upvotes: 7

Andy Thomas
Andy Thomas

Reputation: 86509

The MyString copy constructor is not needed to call this statement, because MyString is passed as a reference to the custom operator<< for MyString.

The endl is not sent to the custom operator<< for MyString.

Upvotes: 0

Related Questions