I have two questions about overloading.
1- Why sometimes do make overloading operators non-member functions?
friend Class operator-(const Class &rhs);
2- What’s the difference between
Class operator+(const Class &c1, const Class &c2);
and
Class operator+(const Class &rhs);
if I want to add two objects C3 = C1 + C2?
Any help is appreciated…
If you overload a binary operator as a member function, it ends up asymmetrical: the left operand must be the exact type for which the operator is overloaded, but the right operand can be anything that can be converted to the correct type.
If you overload the operator with a non-member function, then both operands can be converted to get the correct type.
What you have as your second point looks like a concrete example of the same point, not really anything separate at all. Here’s a concrete example of what I’m talking about:
Also note that even though the definition of the
friendfunction is inside the class definition forInteger, the fact that it’s declared as a friend means it’s not a member function — declaring it asfriendmakes it a global function, not a member.Bottom line: such overloads should usually be done as free functions, not member functions. Providing the user with an operator that works correctly (drastically) outweighs theoretical considerations like “more object oriented”. When necessary, such as when the implementation of the operator needs to be virtual, you can do a two-step version, where you provide a (possibly virtual) member function that does the real work, but the overload itself is a free function that invokes that member function on its left operand. One fairly common example of this is overloading
operator<<for a hierarchy:This supports both polymorphic implementation (and access to a base class’ protected members, if necessary) without giving up the normal characteristics of the operator to get it.
The primary exceptions to overloading binary operators as free functions are assignment operators (
operator=,operator+=,operator-=,operator*=and so on). A conversion would produce a temporary object, which you can’t assign to anyway, so for this particular case, the overload should be (must be, as a matter of fact) a member function instead.