Operator Overloading Custom Output Stream in C++
C++
It can be useful to display data from a user-defined type (e.g. an object instantiated from a class) using the std::cout
object. This can be achieved by overloading the <<
operator.
This would allow you to print selected data members in a meaningful way. For example, if you have a class Point
which holds data members x
and y
to represent horizontal and vertical displacement, the following might be a useful way to display a Point
object:
Point a(10, 2);
std::cout << a << std::endl;
// Prints "(10, 2)"
You need to set up the insertion operator such that it accepts an std::ostream
object on the left and a user-defined type on the right. You achieve this by declaring the overloaded operator as a friend of the class. This allows the function to accept the required parameters, and provides access to private data within the class.
The function is then defined as a free operator -i.e. not a member of a class.
Example
// Point.h
#include <iostream>
class Point {
friend std::ostream& operator<<(std::ostream& os, Point p);
private:
float m_x;
float m_y;
public:
Point(float x, float y);
};
// Point.cpp
#include "Point.h"
// Member function declarations
Point::Point(float x, float y) : m_x(x), m_y(y)
{}
...
std::ostream& operator<<(std::ostream& os, Point p)
{
// Because this is a friend function, we have access to the object's private data
os << "(" << p.m_x << ", " << p.m_y << ")";
return os;
}
Implementation in main.cpp:
...
Point a(99.9, 2.3);
std::cout << a << std::endl;
// Output: (99.9, 2.3)
Don’t Declare the Operator Overload as a Member of the Class
If you declare the operator<<
as a non-static data member - i.e. if it is declared in the class, accepting a std::iostream&
and Point
as parameters, it will cause a compiler error:
g++ -W -Wall -std=c++17 -o bin/main Point.cpp main.cpp
In file included from Point.cpp:1:0:
Point.h:14:53: error: ‘std::ostream& Point::operator<<(std::ostream&, Point)’ must take exactly one argument
std::ostream& operator<<(std::ostream& os, Point p);
This occurs because:
- A non-static member method takes an implicit
this
parameter that is passed as a hidden argument - The
<<
operator takes exactly two arguments e.g. fora << b
, the arguments area
andb
- Declared as a member function, there are too many arguments!
It doesn’t make logical sense for the overloaded <<
operator to be a member function, since in it’s implementation it needs to get data from a passed in object and pass this along to the output stream.
TLDR;
- Declare the
operator<<
as a friend of the class. - DO NOT define the function as a member of the class - define it as a free function outside the class.
- The friend declaration ignores the private/public designators
References
comments powered by Disqus