When an operator function is implemented as a member function, the leftmost (or
only) operand must be an object (or a reference to an object) of the operator’s class. If the
left operand must be an object of a different class or a fundamental type, this operator function
must be implemented as a non-member function (e.g. when overloading <<
and >>
as the stream insertion and stream extraction operators, respectively).
A non-member operator function can be made a friend
of a class if that function
must access private
or protected
members of that class directly. Operator member functions of a specific class are called (implicitly by the compiler) only when the left operand of a binary operator is specifically an object of that class, or when the single operand of a unary operator is an object of that class.
Another reason why you might choose a non-member function to overload an operator is to
enable the operator to be commutative.
For example, suppose we have a fundamental type variable, number
, of type long int
, and an object bigInteger1
, of class HugeInteger
(a class in which integers may be arbitrarily large rather than being limited by the machine word size of the underlying hardware). The subtraction operator (-
) produces a temporary HugeInteger
object as the difference of a HugeInteger
and a long int
(as in the expression bigInteger1 - number
), or as the difference of a long int
and a HugeInteger
(as in the expression number - bigInteger1
). Thus, we require the subtraction operator to be commutative (exactly as it is with two fundamental-type operands). The problem is that the class object must appear on the left of the subtraction operator if that operator is to be overloaded as a member function. So, we also overload the operator as a non-member function to allow the HugeInteger
to appear on the right of the subtraction. The operator-
function that deals with the HugeInteger
on the left can still be a member function. The non-member function can simply swap its arguments and call the member function.