Navigation



9.3 — Overloading the I/O operators

Overloading <<

For classes that have multiple member variables, printing each of the individual variables on the screen can get tiresome fast. For example, consider the following class:

class Point
{
private:
    double m_dX, m_dY, m_dZ;

public:
    Point(double dX=0.0, double dY=0.0, double dZ=0.0)
    {
    m_dX = dX;
    m_dY = dY;
    m_dZ = dZ;
    }

    double GetX() { return m_dX; }
    double GetY() { return m_dY; }
    double GetZ() { return m_dZ; }
};

If you wanted to print an instance of this class to the screen, you’d have to do something like this:

Point cPoint(5.0, 6.0, 7.0);
cout << "(" << cPoint.GetX() << ", " <<
    cPoint.GetY() << ", " <<
    cPoint.GetZ() << ")";

And that’s just for one instance! It would be much easier if you could simply type:

Point cPoint(5.0, 6.0, 7.0);
cout << cPoint;

and get the same result. By overloading the << operator, you can! Overloading operator<< is similar to overloading operator+ (they are both binary operators), except that the parameter types are different.

Consider the expression cout << cPoint. If the operator is <<, what are the operands? The left operand is the cout object, and the right operand is your Point class object. cout is actually an object of type ostream. Therefore, our overloaded function will look like this:

friend ostream& operator<< (ostream &out, Point &cPoint);

Implementation of operator<< is fairly straightforward -- because C++ already knows how to output doubles using operator<<, and our members are all doubles, we can simply use operator<< to output the member variables of our Point. Here is the above Point class with the overloaded operator<<.

class Point
{
private:
    double m_dX, m_dY, m_dZ;

public:
    Point(double dX=0.0, double dY=0.0, double dZ=0.0)
    {
    m_dX = dX;
    m_dY = dY;
    m_dZ = dZ;
    }

    friend ostream& operator<< (ostream &out, Point &cPoint);

    double GetX() { return m_dX; }
    double GetY() { return m_dY; }
    double GetZ() { return m_dZ; }
};

ostream& operator<< (ostream &out, Point &cPoint)
{
    // Since operator<< is a friend of the Point class, we can access
    // Point's members directly.
    out << "(" << cPoint.m_dX << ", " <<
        cPoint.m_dY << ", " <<
        cPoint.m_dZ << ")";
    return out;
}

This is pretty straightforward -- note how similar our output line is to the line we wrote when we were outputting our members manually. They are almost identical, except cout has become parameter out!

The only tricky part here is the return type. Why are we returning an object of type ostream? The answer is that we do this so we can "chain" output commands together, such as cout << cPoint << endl;

Consider what would happen if our operator<< returned void. When the compiler evaluates cout << cPoint << endl;, due to the precedence/associativity rules, it evaluates this expression as (cout << cPoint) << endl;. cout << cPoint calls our void-returning overloaded operator<< function, which returns void. Then the partially evaluated expression becomes: void << endl;, which makes no sense!

By returning the out parameter as the return type instead, (cout << cPoint) returns cout. Then our partially evaluated expression becomes: cout << endl;, which then gets evaluated itself!

Any time we want our overloaded binary operators to be chainable in such a manner, the left operand should be returned.

Just to prove it works, consider the following example, which uses the Point class with the overloaded operator<< we wrote above:

int main()
{
    Point cPoint1(2.0, 3.0, 4.0);
    Point cPoint2(6.0, 7.0, 8.0);

    using namespace std;
    cout << cPoint1 << " " << cPoint2 << endl;

    return 0;
}

This produces the following result:

(2.0, 3.0, 4.0) (6.0, 7.0, 8.0)

Overloading >>

It is also possible to overload the input operator. This is done in a manner very analogous to overloading the output operator. The key thing you need to know is that cin is an object of type istream. Here's our Point class with an overloaded operator>>:

class Point
{
private:
    double m_dX, m_dY, m_dZ;

public:
    Point(double dX=0.0, double dY=0.0, double dZ=0.0)
    {
    m_dX = dX;
    m_dY = dY;
    m_dZ = dZ;
    }

    friend ostream& operator<< (ostream &out, Point &cPoint);
    friend istream& operator>> (istream &in, Point &cPoint);

    double GetX() { return m_dX; }
    double GetY() { return m_dY; }
    double GetZ() { return m_dZ; }
};

ostream& operator<< (ostream &out, Point &cPoint)
{
    // Since operator<< is a friend of the Point class, we can access
    // Point's members directly.
    out << "(" << cPoint.m_dX << ", " <<
        cPoint.m_dY << ", " <<
        cPoint.m_dZ << ")";
    return out;
}

istream& operator>> (istream &in, Point &cPoint)
{
    in >> cPoint.m_dX;
    in >> cPoint.m_dY;
    in >> cPoint.m_dZ;
    return in;
}

Here's a sample program using both the overloaded operator<< and operator>>:

int main()
{
    using namespace std;
    cout << "Enter a point: " << endl;

    Point cPoint;
    cin >> cPoint;

    cout << "You entered: " << cPoint << endl;

    return 0;
}

Assuming the user enters 3.0 4.5 7.26 as input, the program produces the following result:

You entered: (3, 4.5, 7.26)

Conclusion

Overloading operator<< and operator>> make it extremely easy to output your class to screen and accept user input.

Before we finish this lesson, there is one additional point that is important to make. The overloaded output operator<<

friend ostream& operator<< (ostream &out, Point &cPoint);

is actually better written as

friend ostream& operator<< (ostream &out, const Point &cPoint);

This way, you will be able to output both const and non-const objects.

However, for the overloaded input operator>>, you will have to leave cPoint as non-const because the overloaded operator>> modifies cPoints members.

By now, you should be starting to become comfortable with classes and passing parameters by reference. In future lessons, we will start making more of our parameters const references (which we should have been doing all along, but have abstained for purposes of simplicity). It is a good habit to get into early.

9.4 -- Overloading the comparison operators
Index
9.2 -- Overloading the arithmetic operators

51 comments to 9.3 — Overloading the I/O operators

  • [...] If you need a refresher on chaining, we cover that in the section on overloading the I/O operators. [...]

  • Jason

    I understand everything on this page well enough to overload I/O operators. I feel I grasp everything that has been presented here.

    Still, I’m left wondering what goes on under the hood. For example:

    ostream& operator< < (ostream &out, Point &cPoint)
    

    What does the & (reference operator) do here: ostream& operator< < I believe this is the first time I've seen anything like that, a reference to a function or something? Does this maybe somehow tie into function pointers?

    I'm in a little over my head at this point. I'm wondering if it's even important to know what's going on under the hood with this issue.

    Your thoughts?

    • Jason

      What really had me confused was the return by reference statement. This ostream& operator< < was confusing me simply because returning a value by reference is something I had not seen or done up until this point. It took me a little while to make sense of this. Anyway, here is some code that I came up with that helped me understand what takes place when returning a value by reference.

      #include 
      using namespace std;
      
      int x = 11;
      
      int& ref()
      	{
      	return x;
      	}
      
      int main()
      	{
      	int *ptr = &ref();  //after the return by reference
                            //takes place, &ref() is &x
      
      	*ptr = 12;
      	cout < < x << endl;
      
      	return 0;
      	}
      

      • There really isn’t much difference between return statements and function parameters, except for the directionality of the data transfer and the fact that you can only have one return value.

        Pretty much everything you’ve learned about pass by value, reference, and address apply to return values in the same way that they apply to parameters.

  • Jason, ostream is a class provided as part of C++ that handles outputs streams. The details of how ostream is implemented is very complex, but fortunately also completely unnecessary to use it effectively.

    Since ostream is a class, ostream& is a reference to an ostream class. Note that we’re also taking an ostream& as a parameter. ostream is typically passed by reference because we don’t want to make a copy of it as we pass it around.

    So basically, our overloaded function takes an ostream as a parameter, writes stuff to it, and then returns the same ostream. This allows us to chain < < calls together:


    cout < < cPoint1 << cPoint2 << cPoint3;

    This resolves as follows:


    ((cout < < cPoint1) << cPoint2) << cPoint3;

    cout < < cPoint1 is resolved first, with cout becoming the ostream& parameter. When this overloaded function is finished writing to the out parameter, it returns that cout so the next call to < < can use it. Thus:


    ((cout < < cPoint1) << cPoint2) << cPoint3;

    becomes:


    (cout < < cPoint2) << cPoint3;

    becomes:


    cout < < cPoint3;

    This calls our overloaded function one last time. At the end of this function, cout is again returned. But there's nobody left to use it, so the return value is ignored. The expression ends, and the program moves to the next line.

  • Jason

    Hmm, can I reference my own classes in a manner similar to the way ostream& references an ostream class? If that is possible, could it be useful.

    Curiosity killed the cat! :)

  • Yes. This is typically done in two ways.

    Let’s say you wrote a class named Foo.

    If you are writing a function that lives outside of Foo:

    Foo& FunctionName(Foo& cFoo, other params here)
    {
        // use cFoo
        return cFoo;
    }
    

    If writing a function that is a member of Foo:

    Foo& Foo::FunctionName(other params here)
    {
        // use implicit Foo object
        return *this;
    }
    
  • Jason

    Then I shall in good time have to experiment coding a reference to a class. I imagine this will increase my understanding of the ostream implementation.

  • [...] extraction operations for all of the built-in data types, and you’ve already seen how you can overload the extraction operator for your own [...]

  • Tom

    Alex -

    I don’t understand why this:

    ostream& operator< < (ostream &out, Point &cPoint)
     {
         out << "(" << cPoint.GetX() << ", " <<
             cPoint.GetY() << ", " <<
             cPoint.GetZ() << ")";
         return out;
     }
    

    isn't written like this:

    ostream& operator< < (ostream &out, Point &cPoint)
     {
         cout << "(" << cPoint.GetX() << ", " <<
             cPoint.GetY() << ", " <<
             cPoint.GetZ() << ")";
         return cout;
     }
    

    I guess I don't get the difference between "out" and "cout".

    ????

    Thanks.

    • Good question! Here’s what I think you might be missing: out might not be cout. It might be cerr (an output stream used for error conditions), or a file ostream object (an output stream for writing to a file instead of the screen). You’ll learn about both of these in the chapter on I/O. In those cases, we don’t want to write to cout, we want to write to whatever alternative output stream we’re using. Those alternative streams come into the overloaded < < operator as the "out" parameter.

      For example:


      cerr < < "You have hit error # " << nErrorNum << endl;

      This is broken up like this:


      ((cerr < < "You have hit error # ") << nErrorNum) << endl;

      cerr's overloaded extraction operator will receive cerr as the "out" parameter, and "You have hit error # " as a string parameter. When it is done loading the stream, it will return cerr. Then evaluation will continue, and we will have:


      (cerr < < nErrorNum) << endl;

      cerr's overloaded extraction operator will receive cerr as the "out" parameter, and nErrorNum as an integer parameter. When it is done putting the value of nErrorNum in the stream, it will return cerr again, and evaluation will continue:


      cerr < < endl;

      Again, cerr's overloaded extraction operator will receive cerr as the "out" parameter, and endl as it's other parameter. It will do it's thing, return cerr, and evaluation will continue. At this point, there's nothing left to evaluate, so evaluation is complete.

      If we had returned cout instead of out, then nErrorNum and endl would have been printed to cout instead of cerr!

  • [...] 2007 Prev/Next Posts « 9.3 — Overloading the I/O operators | Home | 9.5 — Overloading unary operators +, -, and ! » Thursday, October 4th, [...]

  • simon simpson

    I am using Visual Studio 2005.
    I can’t get the following to compile:

    friend ostream& operator<< (ostream &out, Point &cPoint);

    I get two errors relating to this:

    error C2143: syntax error : missing ‘;’ before ‘&’

    error C2433: ‘ostream’ : ‘friend’ not permitted on data declarations

    I have used the Point example listed above exactlly.

    Can anyone help?

    • davidv

      error C2143: syntax error : missing ‘;’ before ‘&’

      to fix this, simply put semi-colon at the end of the previous function declaration

      error C2433: ‘ostream’ : ‘friend’ not permitted on data declarations

      this will be fine if you put “using namespace std” right at the beginning of your code, so that it has global impact

  • siku

    public:
    Point(double dX=0.0, double dY=0.0, double dZ=0.0)
    {
    m_dX = dX;
    m_dY = dY;
    m_dZ = dZ;
    }; //Put semicolon on this line, it should help!

    friend ostream& operator<< (ostream &out, Point &cPoint);

    ” PRE” tags doen’t work for me.

  • M.N. Jayaram

    Hi

    The operator << being a friend of the class can directly access the member variables & avoid the costly function calls as below.

    ostream& operator<< (ostream &out, Point &cPoint)
    {
        out << "(" << cPoint.m_dX << ", " <<
            cPoint.m_dY << ", " <<
            cPoint.m_dZ << ")";
        return out;
    }
    

    [ Good point. Examples updated. Thanks! -Alex ]

  • George D

    Hi

    I also have a problem that I cannot understand. I tried to compile my code with GNU C++. Here is a part of my code:

    The header file

    class BitArray {
    			private:
    			valarray< byte_t > data;
    			number_t bit_len;
    			public:
    			// Constructors
    			BitArray();
    			explicit BitArray( BitArray& );
    			explicit BitArray( uint_t );
    			BitArray& operator= ( const BitArray& );
    			// Destructor
    			~BitArray();
    			// Const functions
    			number_t getBitSize() const;
    			number_t getWordSize() const;
    			valarray< byte_t > getArray() const;
    			bool getBit( number_t ) const;
    			// Set functions
    			void resize( number_t, bool );
    			void setBit( number_t, bool );
    			void reverse();
    			// Operators
    			bool operator== ( const BitArray& );
    			BitArray& operator^ ( const BitArray& );
    			BitArray& operator& ( const BitArray& );
    			BitArray& operator| ( const BitArray& );
    			const bool operator[] ( number_t ) const;
    			friend ostream& operator<< ( ostream&, const BitArray& );
    		};
    

    The source:

    ostream& BitArray::operator<< ( ostream& _stream, const BitArray& _arr ) {
    	string to_write;
    	for( int i = 0; i < _arr.getBitSize(); i++ ) {
    		if( _arr[ i ] )
    			to_write += "1";
    		else
    			to_write += "0";
    	}
    	_stream << to_write;
    	return _stream;
    }
    

    The compiler sends the following error message: “/home/demarcsek/dev/Kalaha3/src/KCompress.h:63: error: ‘std::ostream& Kalaha::KCompress::BitArray::operator<<(std::ostream&, const Kalaha::KCompress::BitArray&)’ must take exactly one argument”
    When I modified this function with only one argument as a const BitArray& and used cout as a default stream, the compiler wrote the following message: “/home/demarcsek/dev/Kalaha3/src/KCompress.h:63: error: ‘std::ostream& Kalaha::KCompress::BitArray::operator<<(std::ostream&, const Kalaha::KCompress::BitArray&)’ must take exactly two arguments”

    It’s funny…Can anybody help me?

    Thanks,
    George

    • Joris

      ostream& BitArray::operator<< ( ostream& _stream, const BitArray& _arr )
      { //implementation
      return _stream;
      }
      That’s wrong – it shouldn’t be member function of the Bitarray class. Instead, it should be a “global” function:

      Instead use this:

      ostream& operator<< ( ostream& _stream, const BitArray& _arr )
      { //implementation
      return _stream;
      }

  • rehab

    why it should be friend?

    • Benjamin

      If you implement it as a member, it will have to be a member of ‘ostream’, taking one ‘Point’ as parameter:

      ostream& ostream::operator<<(Point& p);

      In c++ we can’t reopen and extend the ostream-class, so we have to use a friend function.

      Think of it the other way:
      if you implemented it as a member of ‘Point’…

      ostream& Point::operator<<(ostream& out);

      … you could pass a ‘ostream’ to the ‘Point’ class through the ‘<<’-operator:

      Point p;
      ostream o;
      p << o;

      This compiles, but (in our case) it doesn’t make any sence.

      Hope this helped!

      [offtopic]in some languages (i.e. ruby) you can reopen and extend existing classes (i.e. ‘ostream’)[/offtopic]

  • RevWaldo

    In the above example – any many others like it on the web – the code is written thus:

    ostream& operator<< (ostream &out, Point &cPoint)
    

    Meanwhile many other texts – including a C++ textbook I’m using – would write it as:

    ostream &operator<< (ostream &out, Point &cPoint)
    

    I imagine the complier just ignores the difference in whitespace, but what’s up with that? The first version makes more sense to me, while the second makes me scratch my head. Can anyone clarify why they’d write it differently? Or are they actually different?

    • serenity

      This is purely a matter of style. Choose whichever you prefer, since as you guessed, the whitespace is ignored by the compiler.

      I don’t have a reason for it that I can explain, but I prefer “char *func()” and “char &func()” over “char* func()” and “char& func()”. I guess I was raised that way. ;)

  • bob

    Ok, so how would you overload the input operator if you wanted to input both an integer and a string (such that the string could pick up long srings with spaces, not single words…)…

    For example:

    istream &operator >> (istream &in, CLASS1 &x)
    {
    	// temp variables
    	string TempString;
    	int TempInt;
    
    	cout<< "Enter Your Full Name Name: ";
    	in >> TempString;
    	cout<< "Enter Your Age: ";
    	in >> TempInt;
    other code...
    }
    

    The above will only take in a word. Apologies if this is a basic question. I’m a first timer.

    - Bob

  • the line cout<<date1+date2 outputs wrong result, i cannot find why..

    class Date
    {
    private:
        int m_nMonth;
        int m_nDay;
        int m_nYear;
    
        Date() { } // private default constructor
    
    public:
        Date(int nMonth, int nDay, int nYear)
        {
            SetDate(nMonth, nDay, nYear);
        }
    
        void SetDate(int nMonth, int nDay, int nYear)
        {
            m_nMonth = nMonth;
            m_nDay = nDay;
            m_nYear = nYear;
        }
    
        friend Date& operator+ ( const Date& date1, const Date& date2);
        friend ostream& operator<< (ostream& out, const Date& date1);
    
        void PrintMonth()  {cout<<m_nMonth<<endl;}
    
        int GetMonth() const { return m_nMonth; }
        int GetDay() const { return m_nDay; }
        int GetYear() const { return m_nYear; }
    };
    
    Date& operator+ (const  Date& date1, const Date& date2)
    {
    	return Date(date1.m_nMonth+date2.m_nMonth, date1.m_nDay+date2.m_nDay, date1.m_nYear+date2.m_nYear);
    }
    
    ostream& operator<< (ostream& out, const Date& date1)
    {
    	out<<date1.m_nYear<<"/"<<date1.m_nMonth<<"/"<<date1.m_nDay;
    	return out;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	Date date1(11,12,2009);
    	Date date2(1,13,2009);
    	//error,i wonder why, even the following format is alos wrong..cout<<(date1+date2)
    	cout<<date1+date2;
    	Date date3 = date1 + date2;
    	//right
    	cout<<endl<<date3;
    	return 0;
    }
    
  • RSA
    Date& operator+ (const  Date& date1, const Date& date2)
    {
    	Date* newdate = new Date(date1.m_nMonth+date2.m_nMonth, date1.m_nDay+date2.m_nDay, date1.m_nYear+date2.m_nYear);
    	return *newdate;
    }

    this should work now

    • Yes, it works, thanks for your solution. Furthermore, can you explain me why, thanks in advance:)

      • RSA

        This type of error is compiler specific. The reference of the newly created date is no longer valide when the function exits because all the data inside that function are all destroyed. There are few ways to solve this problem, for example you can make static your variable if you consider that its lifetime to be the whole execution of the program. You can make it global and assign with the new operator like I did, but you musn’t forget to delete all variables that used “new” (when the program ends the os deletes them automatically). Here it worked because pointer created with “new” remained in the memory. But you should make it global and delete it if you want to avoid memory leak during execution, or make it static.

  • Sander

    I’m getting those errors trying to compile the last one with giving the point.
    1>d:\documents\visual studio 2008\projects\tryh9\tryh9\tryh9.cpp(20) : error C2143: syntax error : missing ‘;’ before ‘&’
    1>d:\documents\visual studio 2008\projects\tryh9\tryh9\tryh9.cpp(20) : error C2433: ‘ostream’ : ‘friend’ not permitted on data declarations
    1>d:\documents\visual studio 2008\projects\tryh9\tryh9\tryh9.cpp(20) : error C4430: missing type specifier – int assumed. Note: C++ does not support default-int
    1>d:\documents\visual studio 2008\projects\tryh9\tryh9\tryh9.cpp(20) : error C2061: syntax error : identifier ‘ostream’
    1>d:\documents\visual studio 2008\projects\tryh9\tryh9\tryh9.cpp(20) : error C4430: missing type specifier – int assumed. Note: C++ does not support default-int
    1>d:\documents\visual studio 2008\projects\tryh9\tryh9\tryh9.cpp(20) : error C2805: binary ‘operator <d:\documents\visual studio 2008\projects\tryh9\tryh9\tryh9.cpp(21) : error C2143: syntax error : missing ‘;’ before ‘&’
    1>d:\documents\visual studio 2008\projects\tryh9\tryh9\tryh9.cpp(21) : error C2433: ‘istream’ : ‘friend’ not permitted on data declarations
    1>d:\documents\visual studio 2008\projects\tryh9\tryh9\tryh9.cpp(21) : error C4430: missing type specifier – int assumed. Note: C++ does not support default-int
    1>d:\documents\visual studio 2008\projects\tryh9\tryh9\tryh9.cpp(21) : error C2061: syntax error : identifier ‘istream’
    1>d:\documents\visual studio 2008\projects\tryh9\tryh9\tryh9.cpp(21) : error C4430: missing type specifier – int assumed. Note: C++ does not support default-int
    1>d:\documents\visual studio 2008\projects\tryh9\tryh9\tryh9.cpp(21) : error C2805: binary ‘operator >>’ has too few parameters
    1>d:\documents\visual studio 2008\projects\tryh9\tryh9\tryh9.cpp(28) : error C2143: syntax error : missing ‘;’ before ‘&’
    1>d:\documents\visual studio 2008\projects\tryh9\tryh9\tryh9.cpp(28) : error C4430: missing type specifier – int assumed. Note: C++ does not support default-int
    1>d:\documents\visual studio 2008\projects\tryh9\tryh9\tryh9.cpp(28) : error C2086: ‘int ostream’ : redefinition
    1> d:\documents\visual studio 2008\projects\tryh9\tryh9\tryh9.cpp(20) : see declaration of ‘ostream’
    1>d:\documents\visual studio 2008\projects\tryh9\tryh9\tryh9.cpp(28) : error C2065: ‘out’ : undeclared identifier
    1>d:\documents\visual studio 2008\projects\tryh9\tryh9\tryh9.cpp(28) : error C2065: ‘cPoint’ : undeclared identifier
    1>d:\documents\visual studio 2008\projects\tryh9\tryh9\tryh9.cpp(28) : error C2275: ‘Point’ : illegal use of this type as an expression
    1> d:\documents\visual studio 2008\projects\tryh9\tryh9\tryh9.cpp(8) : see declaration of ‘Point’
    1>d:\documents\visual studio 2008\projects\tryh9\tryh9\tryh9.cpp(28) : error C4430: missing type specifier – int assumed. Note: C++ does not support default-int
    1>d:\documents\visual studio 2008\projects\tryh9\tryh9\tryh9.cpp(28) : fatal error C1903: unable to recover from previous error(s); stopping compilation

    how is it possible?

  • awa

    #include
    using namespace std;

    int x = 11;

    int& ref()
    {
    return x;
    }

    int main()
    {
    int *ptr = &ref(); //after the return by reference
    //takes place, &ref() is &x

    *ptr = 12;
    cout < < x << endl;

    return 0;
    }

  • saini

    hi
    would anyone help me to understand that why are we passing both the arguments as a reference and what will happen if we pass them as a value parameter

  • saini
    would anyone help to understand me why are we passing both the arguments as a reference,and what will happen if we pass them as  value parameters
    • Gammerz

      Alex replied to this above:-

      Since ostream is a class, ostream& is a reference to an ostream class. Note that we’re also taking an ostream& as a parameter. ostream is typically passed by reference because we don’t want to make a copy of it as we pass it around.

  • Gammerz

    When the operator<< function becomes a friend of class Point, it allows us direct access to the member variables m_dX, m_dY and m_dZ. We could avoid making the operator<< a friend of the class Point and instead use member functions GetX(), GetY() and GetZ(), for improved encapsulation. Is this example purely to demonstrate the use of the "friend" command or are we saying this is a preferred method?

  • ARVIND

    While overloading output stream operator << as member member function I am getting following error:

    ostreamOprt.cpp:32: error: no match for 'operator<<' in 'std::cout << objs'
    /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/ostream.tcc:63: note: candidates are: std::basic_ostream& std::basic_ostream
    ::operator<<(std::basic_ostream&(*)(std::basic_ostream&)) [with _CharT = char, _Traits = std:
    :char_traits]
    /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/ostream.tcc:74: note: std::basic_ostream& std::basic_ostream::operator<<(std::basic_ios&(*)(std::basic_ios&)) [with _CharT = char, _Traits = std::char_traits]
    /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/ostream.tcc:86: note: std::basic_ostream& std::basic_ostream::operator<<(std::ios_base&(*)(std::ios_base&)) [with _CharT = char, _Traits = std::char_traits]
    /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/ostream.tcc:121: note: std::basic_ostream& std::basic_ostream::operator<<(long int) [with _CharT = char, _Traits = std::char_traits]
    /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/ostream.tcc:155: note: std::basic_ostream& std::basic_ostream::operator<<(long unsigned int) [with _CharT = char, _Traits = std::char_traits]
    /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/ostream.tcc:98: note: std::basic_ostream& std::basic_ostream::operator<<(bool) [with _CharT = char, _Traits = std::char_traits]
    /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/ostream:178: note: std::basic_ostream& std::basic_ostream::oper
    ator<<(short int) [with _CharT = char, _Traits = std::char_traits]
    /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/ostream:189: note: std::basic_ostream& std::basic_ostream::oper
    ator<<(short unsigned int) [with _CharT = char, _Traits = std::char_traits]
    /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/ostream:193: note: std::basic_ostream& std::basic_ostream::oper
    ator<<(int) [with _CharT = char, _Traits = std::char_traits]
    /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/ostream:204: note: std::basic_ostream& std::basic_ostream::oper
    ator<<(unsigned int) [with _CharT = char, _Traits = std::char_traits]
    /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/ostream.tcc:179: note: std::basic_ostream& std::basic_ostream::operator<<(long long int) [with _CharT = char, _Traits = std::char_traits]
    /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/ostream.tcc:214: note: std::basic_ostream& std::basic_ostream::operator<<(long long unsigned int) [with _CharT = char, _Traits = std::char_traits]
    /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/ostream.tcc:238: note: std::basic_ostream& std::basic_ostream::operator<<(double) [with _CharT = char, _Traits = std::char_traits]
    /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/ostream:219: note: std::basic_ostream& std::basic_ostream::oper
    ator<<(float) [with _CharT = char, _Traits = std::char_traits]
    /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/ostream.tcc:261: note: std::basic_ostream& std::basic_ostream::operator<<(long double) [with _CharT = char, _Traits = std::char_traits]
    /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/ostream.tcc:284: note: std::basic_ostream& std::basic_ostream::operator<<(const void*) [with _CharT = char, _Traits = std::char_traits]
    /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/ostream.tcc:307: note: std::basic_ostream& std::basic_ostream::operator<<(std::basic_streambuf*) [with _CharT = char, _Traits = std::char_traits]
    /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/ostream:449: note: std::basic_ostream& std::operator<<(std::basic_ostream&, char) [with _CharT = char, _Traits = std::char_traits]
    /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/ostream.tcc:505: note: std::basic_ostream& std::operator<<(std::basic_ostream
    &, char) [with _Traits = std::char_traits]
    /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/ostream:460: note: std::basic_ostream& std::operator<<(std::basic_ostream&, signed char) [with _Traits = std::char_traits]
    /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/ostream:465: note: std::basic_ostream& std::operator<<(std::basic_ostream&, unsigned char) [with _Traits = std::char_traits]
    /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/ostream.tcc:567: note: std::basic_ostream& std::operator<<(std::basic_ostre
    am&, const char*) [with _CharT = char, _Traits = std::char_traits]
    /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/ostream.tcc:612: note: std::basic_ostream& std::operator<<(std::basic_ostream
    &, const char*) [with _Traits = std::char_traits]
    /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/ostream:499: note: std::basic_ostream& std::operator<<(std::basic_ostream&, const signed char*) [with _Traits = std::char_traits]
    /usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/ostream:504: note: std::basic_ostream& std::operator<<(std::basic_ostream&, const unsigned char*) [with _Traits = std::char_traits]

    Alex can you please explain why?

  • rebelsoul

    Hello Alex,
    Thank you for such a good tutorial. I am facing a problem while running the above given code. I am using visual studio 2008, following your code and same input. However in result only the first input variable value is printed the rest are discarded.
    Here is a extract after debug.
    cPoint {m_dX=6.0000000000000000 m_dY=0.00000000000000000 m_dZ=0.00000000000000000

    Could you please guide, why the program is not taking all the value?

  • [...] insertion operations for all of the built-in data types, and you’ve already seen how you can overload the insertion operator for your own [...]

  • sw1983

    Hello, my compiler (visual c++ 2010) will not recognise ostream. It is saying it is an undeclared identifier. I’ve double checked and ostream is in the iostream library, I’ve included iostream. I thought it was something I was doing but I have copied and pasted Alex’s code into my program and still I get the same error. What am I missing? I haven’t written the function yet because the syntax gets underlined in red so I know it won’t compile anyway.


    #include <iostream>
    #include <string>

    class Employee
    {
    private:
    static int sm_nID;
    int m_nID ;
    char m_strName[25];
    double m_dWage;

    public:
    Employee(char *strName="Blank", double dWage=10.00)
    {
    using namespace std;
    strncpy_s(m_strName, strName, 25);
    m_nID = ++sm_nID;
    m_dWage = dWage;
    }

    char* GetName()
    {
    return m_strName;
    }

    int GetID()
    {
    return m_nID;
    }

    double GetWage()
    {
    return m_dWage;
    }

    void Print()
    {
    using namespace std;
    cout << "Name: " << m_strName << "\t" << "Employee ID: " << m_nID << "\t" <<
    "Wage: " << m_dWage << "\n";
    }

    static void PrintID()
    {
    std::cout << sm_nID;
    }

    friend void ResetName(Employee &cEmployee);
    friend class FriendOfMine;
    /****************************HERE**************************************************/
    friend ostream& operator<< (ostream &out, Employee &cEmployee);
    };

    /****************************HERE**************************************************/

    ostream& operator<< (ostream &out, Employee &cEmployee)
    {

    }

    int Employee::sm_nID = 0;

    void ResetName(Employee &cEmployee)
    {
    strncpy(cEmployee.m_strName, "Reset", 25);
    }

    class FriendOfMine
    {
    public:
    void WageChange(Employee &cEmployee)
    {
    cEmployee.m_dWage = 5;
    }
    };

    int main()
    {

    return 0;
    }

  • sw1983

    Nevermind I’d forgotten to use the namespace. haha, kick myself.

  • zynk

    ostream& operator<< (ostream &out, Point &cPoint)
    {
    // Since operator<< is a friend of the Point class, we can access
    // Point's members directly.
    out << "(" << cPoint.m_dX << ", " <<
    cPoint.m_dY << ", " <<
    cPoint.m_dZ << ")";
    return out;
    }

    Hey Alex
    we are returning a reference to the object 'out', which has local scope. Is it legal??

  • etam

    You should mention that “<>” are originally arithmetic bitwise shift operators. http://en.cppreference.com/w/cpp/language/operator_arithmetic

  • Monster

    Thanks alot for accepting me as a member in this great website.
    I am interested in learning C++ so much and this website is a great source to depend on in learning C++…..

  • [...] If you need a refresher on chaining, we cover that in the section on overloading the I/O operators. [...]

  • [...] extraction operations for all of the built-in data types, and you’ve already seen how you can overload the extraction operator for your own [...]

  • [...] insertion operations for all of the built-in data types, and you’ve already seen how you canoverload the insertion operator for your own [...]

  • WONDERFUL TUTORIAL BY MR.ALEX..

    I REALLY UNDERSTAND….

  • yakisobskie

    Hi Alex! Great tutorial! btw Everything worked except for the operand>> tutorial. I’m getting an error “no match for operator>>…”. I’m unable to understancd istream.

    How come there is no match for operand>>(istream, double) while
    operand<<(ostream, double) is working fine? Thanks!

    01| #include
    02| using namespace std;
    .
    .
    .

    34| istream& operator>> (istream& x, const Point& y)
    35| {
    36| x >> y.m_dX;
    37| x >> y.m_dY;
    38| x >> y.m_dZ;
    39| return x;
    40| }

    |36|error: no match for ‘operator>>’ (operand types are ‘std::istream {aka std::basic_istream}’ and ‘const double’)|

  • [...] 9.3 — Overloading the I/O operators « Learn C++ – What really had me confused was the return by reference statement. This ostream& operator was confusing me simply because returning a value by reference is …… [...]

You must be logged in to post a comment.