|

Declare
an overloaded operator as you would a function.
Use the keyword operator, followed by the operator
to overload. Unary operator functions do not take
parameters, with the exception of the postfix increment
and decrement, which take an integer as a flag.
Example 1
const
Counter& Counter::operator++ ();
Example
2
Counter
Counter::operator-(int);
DO
use a parameter to operator++ if you want the postfix
operator. DO return a const reference to
the object from operator++. DON’T create
temporary objects as return values from operator++.
The
Addition Operator
The
increment operator is a unary operator. It operates
on only one object. The addition operator (+) is
a binary operator, where two objects are involved.
How do you implement overloading the + operator
for Count?
The
goal is to be able to declare two Counter variables
and then add them, as in this example:
Counter
varOne, varTwo, varThree;
VarThree
= VarOne + VarTwo;
Once
again, you could start by writing a function, Add(),
which would take a Counter as its argument, add
the values, and then return a Counter with the result.
Listing 10.13 illustrates this approach.
Listing
10.13. The Add() function.
1:
// Listing 10.13
2:
// Add function
3:
4:
typedef unsigned short USHORT;
5:
#include <iostream.h>
6:
7:
class Counter
8:
{
9:
public:
10:
Counter();
11:
Counter(USHORT initialValue);
12:
~Counter(){}
13:
USHORT GetItsVal()const { return itsVal; }
14:
void SetItsVal(USHORT x) {itsVal = x; }
15:
Counter Add(const Counter &);
16:
17:
private:
18:
USHORT itsVal;
19:
20:
};
21:
22:
Counter::Counter(USHORT initialValue):
23:
itsVal(initialValue)
24:
{}
25:
26:
Counter::Counter():
27:
itsVal(0)
28:
{}
29:
30:
Counter Counter::Add(const Counter & rhs)
31:
{
32:
return Counter(itsVal+ rhs.GetItsVal());
33:
}
34:
35:
int main()
36:
{
37:
Counter varOne(2), varTwo(4), varThree;
38:
varThree = varOne.Add(varTwo);
39:
cout << "varOne: " << varOne.GetItsVal()<<
endl;
40:
cout << "varTwo: " << varTwo.GetItsVal()
<< endl;
41:
cout << "varThree: " << varThree.GetItsVal()
<< endl;
42:
43:
return 0;
44:
}
OUTPUT:
varOne:
2
varTwo:
4
varThree:
6
Analysis: The Add()function is declared
on line 15. It takes a constant Counter reference,
which is the number to add to the current object.
It returns a Counter object, which is the result
to be assigned to the left side of the assignment
statement, as shown on line 38. That is, VarOne
is the object, varTwo is the parameter to the Add()
function, and the result is assigned to VarThree.
In order to create varThree without having to initialize
a value for it, a default constructor is required.
The default constructor initializes itsVal to 0,
as shown on lines 26-28. Since varOne and varTwo
need to be initialized to a non-zero value, another
constructor was created, as shown on lines 22-24.
Another solution to this problem is to provide the
default value 0 to the constructor declared on line
11.
Overloading
operator+
The
Add() function itself is shown on lines 30-33. It
works, but its use is unnatural. Overloading the
+ operator would make for a more natural use of
the Counter class. Listing 10.14 illustrates this.
Listing
10.14. operator+.
1:
// Listing 10.14
2:
//Overload operator plus (+)
3:
4:
typedef unsigned short USHORT;
5:
#include <iostream.h>
6:
7:
class Counter
8:
{
9:
public:
10:
Counter();
11:
Counter(USHORT initialValue);
12:
~Counter(){}
13:
USHORT GetItsVal()const { return itsVal; }
14:
void SetItsVal(USHORT x) {itsVal = x; }
15:
Counter operator+ (const Counter &);
16:
private:
17:
USHORT itsVal;
18:
};
19:
20:
Counter::Counter(USHORT initialValue):
21:
itsVal(initialValue)
22:
{}
23:
24:
Counter::Counter():
25:
itsVal(0)
26:
{}
27:
28:
Counter Counter::operator+ (const Counter &
rhs)
29:
{
30:
return Counter(itsVal + rhs.GetItsVal());
31:
}
32:
33:
int main()
34:
{
35:
Counter varOne(2), varTwo(4), varThree;
36:
varThree = varOne + varTwo;
37:
cout << "varOne: " << varOne.GetItsVal()<<
endl;
38:
cout << "varTwo: " << varTwo.GetItsVal()
<< endl;
39:
cout << "varThree: " << varThree.GetItsVal()
<< endl;
40:
41:
return 0;
42:
}
OUTPUT:
varOne:
2
varTwo:
4
varThree:
6
ANALYSIS:
operator+
is declared on line 15 and defined on lines 28-31.
Compare these with the declaration and definition
of the Add() function in the previous listing; they
are nearly identical. The syntax of their use, however,
is quite different. It is more natural to say this:
varThree
= varOne + varTwo;
than
to say:
varThree
= varOne.Add(varTwo);
Not
a big change, but enough to make the program easier
to use and understand.
NOTE: The techniques used for overloading
operator++ can be applied to the other unary operators,
such as operator-.
Operator
Overloading: Binary Operators
Binary
operators are created like unary operators, except
that they do take a parameter. The parameter is
a constant reference to an object of the same type.
Example
1
Counter
Counter::operator+ (const Counter & rhs);
Example
2
Counter
Counter::operator-(const Counter & rhs);
Issues
in Operator Overloading
Overloaded
operators can be member functions, as described
in this unit, or non-member functions. The latter
will be described in unit 14, "Special Classes and
Functions," when we discuss friend functions.
The
only operators that must be class members are the
assignment (=), subscript([]), function call (()),
and indirection (->) operators.
operator[]
will be discussed tomorrow, when arrays are covered.
Overloading operator-> will be discussed
in Unit 14, when smart pointers are discussed.
Limitations
on Operator Overloading
Operators
on built-in types (such as int) cannot be overloaded.
The precedence order cannot be changed, and the
arity of the operator, that is, whether it is unary
or binary, cannot be changed. You cannot make up
new operators, so you cannot declare ** to be the
"power of" operator.
New Term: Arity refers to how
many terms are used in the operator. Some C++ operators
are unary and use only one term (myValue++). Some
operators are binary and use two terms (a+b). Only
one operator is ternary and uses three terms. The
? operator is often called the ternary operator,
as it is the only ternary operator in C++ (a >
b ? x : y).
What
to Overload
Operator
overloading is one of the aspects of C++ most overused
and abused by new programmers. It is tempting to
create new and interesting uses for some of the
more obscure operators, but these invariably lead
to code that is confusing and difficult to read.
Of
course, making the + operator subtract and the *
operator add can be fun, but no professional programmer
would do that. The greater danger lies in the well-intentioned
but idiosyncratic use of an operator—using + to
mean concatenate a series of letters, or / to mean
split a string. There is good reason to consider
these uses, but there is even better reason to proceed
with caution. Remember, the goal of overloading
operators is to increase usability and understanding.
DO
use operator overloading when it will clarify the
program. DON’T create counter-intuitive operators.
DO return an object of the class from overloaded
operators.
|