I am trying to overload operator<< as a member function. It works if simply do this:
friend ostream& operator<<(ostream& os, const MyClass& myClass); in my header file and in my MyClass.cc file:
ostream& operator<<(ostream& os, const MyClass& myClass)
{
return myClass.print(os);
}
However, if I try to take the friend off and make it a member function, then it complains that operator<< can only take one argument. Why?
ostream& MyClass::operator<<(ostream& os, const MyClass& myClass)
{
return myClass.print(os);
}
I read at this question that it can’t be a member function, but not sure why?
When overloaded as a member function,
a << bis interpreted asa.operator<<(b), so it only takes one explicit parameter (withthisas a hidden parameter).Since this requires that the overload be part of the class used as the left-hand operand, it’s not useful with normal
ostreams and such. It would require that your overload be part of theostreamclass, not part of your class. Since you’re not allowed to modifyostream, you can’t do that. That leaves only the global overload as an alternative.There is, however, a fairly widely-used pattern where you overload the operator globally, but have that call a member function:
This is particularly useful when/if you want polymorphic behavior. You can’t make the overloaded operator polymorphic itself, but you make the member function it calls
virtual, so it acts polymorphic anyway.Edit: to (I hope) clarify the situation, you can do this a few different ways. The first and probably most obvious is to just make our
writemember public, and have the global operator call it. Since it is public, we don’t have to do anything special to let the operator use it:A second alternative is to make
writeprivate, and declareoperator<<a friend to give it access:There’s a third possibility that’s almost like the second:
This third case uses a rather strange (and little known) rule in C++ called “name injection”. The compiler knows that a
friendfunction can’t be part of the class, so instead of defining a member function, this “injects” the name of that function into the surrounding scope (the global scope, in this case). Even thoughoperator<<is defined inside the class definition, it’s not a member function at all — it’s a global function.