Overloaded operators are based on an operator notation but are implemented as functions. Thoroughly understanding operators, functions, and the member function calling syntax is essential for understanding overloaded operators. Please review the following as needed:
public
and private
keywords)Although overloaded operators and friend functions are independent constructs - it is possible to use one without the other - but programmers often use them together. Fortunately, both are simple extensions to C++ features we have already studied and used, making them an easy addition to our programming toolkit.
C++ implements overloaded operators as functions that follow a specific naming convention and calls them with a specialized but familiar operator notation. For example, C++ allows programs to add two integers using the "+" operator: 5 + 10
, which looks like the way we would write the operation using "pencil and paper." Similarly, a program can specify a class named fraction with an overloaded "+" operator and sum two instances, f1 and f2, with the expression f1 + f2
.
Once you get past the new syntax and a bit of terminology, you'll find that you can apply all your knowledge about functions, both members and non-members, to overloading operators. As a case in point, we have been using overloaded operators all semester but haven't called them that. The inserter, <<
, and the extractor, >>
, operators were originally used in C (and can still be used in C++) as the left and right bit-shift operators. C++ overloads (i.e., reuses) these two operators in the context of streams as the output and input operators, respectively.
C++ implements overloaded operators as functions with the special function name: operator☺
where ☺ is replaced by the overloaded operator. For example, the add function from the Time class example, Time add(Time t);
may be restated as the overloaded operator Time operator+(Time t);
. There are a few basic characteristics that all C++ operators share and that overloaded operators cannot change:
When creating new overloaded operators, programmers cannot
Additionally, overloaded operators should be intuitive, that is, used in a natural way. (For example, if you create a class called Number, you shouldn't define "+" to perform subtraction for two instances of the Number class.) However, what seems intuitive for one programmer may not be so intuitive for another - some have argued that << and >> are not "intuitive" I/O operators. Nevertheless, if you keep that ultimate goal in sight, your overloaded operators will be better in the long run and should be acceptable to other programmers.
This chapter also introduces the friend
keyword that creates functions blurring the line between member and non-member functions:
They:
friend
in the befriending class's specificationprivate
featuresthis
pointer), so they have one more argument (in the parentheses) than a member functionclass_name::
Friend functions are like a trusted neighbor: they are not a family member, but we trust them with keys that allow them to enter our (private) house. By trusting our friends, they can carry out tasks on our behalf (e.g., bringing our mail while we are on vacation) that they could not do otherwise. Similarly, friend functions can perform tasks that not even member functions can do.
The definitions and calls of "normal" functions articulate or match closely, making it relatively easy for programmers to understand the calling syntax. Conversely, implementing an overloaded operator as a function makes its definition strikingly different from the operator-form calling syntax. Asking yourself three questions about a given operator and identifying the answers will help you understand it and its behaviors:
friend
? The distinction affects argument passing and the attribute accessing syntax in the function's body.Number Of Implicit Arguments | Number Of Explicit Arguments | Total Number Of Arguments | ||
---|---|---|---|---|
Unary | Member | 1 | 0 | 1 |
friend | 0 | 1 | 1 | |
Binary | Member | 1 | 1 | 2 |
friend | 0 | 2 | 2 |
function(param1, param2, ...) { ... }
op1 + op2
*x
x * y
this
pointer: x.function(y)
; only member functions have implicit argumentsfunction(x,y)
friend
(i.e. non-member) Functions