![]() |
Essentials of C++: Section XII |
Operator Overloading One can think of C++ operators as symbols (the technical term is
tokens) that trigger some computation. However, exactly what
computation is performed is not fixed. It depends on the operands. For
example, the addition of two integers requires a different set of machine
level instructions than the addition of two doubles. One can therefore
talk about the overloading of operators. Most computer languages do some overloading of operators as part of the
language itself. It is possible, however, in C++ for programmers
themselves to re-define the meaning of C++ operators as long as at least
one of the operands is an instance of a class. Such overloading allows one
to, for example, add two dates using the '+' operator or compare two
weights (in pounds and ounces) using the relational operators. As with
functions, C++ determines which of the computations associated with an
operator to use by looking at the number and types of the operands.
(Operands are to an operator what parameters are to a function.) All operators with the exception of:
can be overloaded. However, different operators have different
restrictions and you should consult your C++ manuals for details
A. Declaring an Overloaded Operator The word 'operator' followed by the operator symbol forms what is
called the operator function name. Thus, we refer to overloaded
operators as function operators or operator functions. For example, if we assume the existence of a class called 'Date', we could declare the overloaded operator function '+' that adds two instances of 'Date'and returns a Date as: The number of arguments (operands) found in an overload declaration
depends on whether the operator function is declared as a friend or member
function of the class in question. (It must be one of the two in order to
have access to the members of the class.) As declared here, the operator
function '+' has two explicit operands, 'd1' and 'd2', and it has access
to the internals of both of them because it is a friend of 'Date'. Since member functions have one implicit argument (a pointer to the instance being "sent the message" - representing by the keyword 'this'), member operator functions need one less explicitly declared operand. Thus the declaration for +=, meaning to add some number of days to a date might be: We could also rewrite the declaration for '+' as: In both these cases we only need one declared operand because the other
operand is implicit. When adding two dates using the friend form of the overloaded '+' operator, the order of the operands is of little importance. Once could, for example, declare three dates as follows:
and write: or However, if we want to use the overloaded '+' operator to add some
number of days to a date, we need to be more careful. By using the
declaration: we are saying that '+' is a member operator function and that the
integer must be to the right of the '+' symbol since the operand to the
left is passed implicitly as a pointer to an instance of 'Date'. When
dealing with member operator functions, the left most operand must be an
instance of a class. It would be more versatile to rewrite this as two
forms: Now one can use this operator with an integer as the left or
right operand. It is important that you carefully analyze the use of any overloaded
operators before you begin writing the declaration(s). Some operators:
must be declared as class members. In other cases, the decision belongs to the programmer. Clearly, if it makes sense for the operator to be commutative (so the operands can change order), the operator function should be made a friend. On the other hand, if the operator is always called with the left most operator being a class instance - as in '+=' in the dates example above - the operator function should be declared as a member of the class. In certain circumstances, the traditional use of the operator
determines how it should be declared. For instance, we always write: To accomplish this (to overload the << operator to accept dates
as a data type) we must overload the << operator as a friend since
the left operand is not an instance of the 'Date' class. Finally, some experts argue that operator functions that have no side
effects should be written as friend functions since they have no effect on
the data members anyway. B. Defining an Overloaded Operator Since this operator returns the data passed in as an implicit parameter
after it has been modified , we return *this. Note that *this is the
result of dereferencing a pointer to a date. In many cases the return type
is declared as 'Date&' to return a reference to the date and avoid a
copy operation.
|