Function Overloading

Operator Overloading
Strong Suggestion: Go over the Array class
example in Section 8.8 of your text. (You
may ignore the Array copy constructor for
now.)
CMSC 202, Version 2/02
1
Review -- Function Signatures
• A function signature is what the compiler
and linker use to identify a function.
• In C, functions are identified only by their
name.
• In C++, a function’s signature includes its
name, parameters, and (for member
functions) const. It does NOT include the
return type.
CMSC 202, Version 2/02
2
A C++ swap( ) Function
• We still need separate functions, but
they can all have the same name.
– void swap (int& a, int& b);
– void swap (double& a, double& b);
– void swap (struct bob& a, struct bob& b);
CMSC 202, Version 2/02
3
Operator Overloading
Overview
• Many C++ operator are already overloaded
for primitive types. Examples:
+ - * / << >>
• It is often convenient for our classes to imitate
the operations available on primitive types
(e.g., + or - ).
• Then we can use the same concise notation
for manipulating our objects.
CMSC 202, Version 2/02
4
A Complex Number Class
class Complex {
public:
Complex (int real = 0, int imagine = 0);
int getReal ( ) const;
int getImagine ( ) const;
void setReal (int n);
void setImagine (int d);
private:
int real;
int imagine;
};
CMSC 202, Version 2/02
5
Using Complex Class
• It makes sense to want to perform
mathematical operations with Complex
objects.
Complex C1 (3, 5), C2 (5, 9), C3;
C3 = C1 + C2; // addition
C2 = C3 * C1;
// subtraction
C1 = -C2;
// negation
CMSC 202, Version 2/02
6
Operators Are Really Functions
• For user-defined types, when you use an
operator, you are making a function call.
• Consider the expression: C2 + C1
– This is translated into a function call.
– The name of the function is “operator+”
– The call is:
C2.operator+(C1);
CMSC 202, Version 2/02
7
Declaring operator+
As a Member Function
class Complex {
public:
const Complex
operator+ (const Complex &rhs) const;
…
};
• Note all of the const’s!
CMSC 202, Version 2/02
8
operator+ Implementation
const Complex
Complex :: operator+ (const Complex &rhs) const
{
Complex sum;
// accessor and mutators not required
sum.imagine = imagine + rhs.imagine;
// but preferred
sum.setReal( getReal( ) + rhs.getReal ( ) );
return sum;
}
CMSC 202, Version 2/02
9
Using operator+
• We can now write
C3 = C2 + C1;
• We can also use cascading operators.
C4 = C3 + C2 + C1;
• And we can write
C3 = C2 + 7;
• But C3 = 7 + C2 is a compiler error. (Why?)
CMSC 202, Version 2/02
10
operator+ As a
Non-member, Non-friend
const Complex
operator+ (const Complex &lhs,
// extra parameter
const Complex &rhs) // not const
{ // must use accessors and mutators
Complex sum;
sum.setImagine (lhs.getImagine( )
+ rhs.getImagine( ) );
sum.setReal (lhs.getReal ( ) + rhs.getReal( ) );
return sum;
} // is now commutative
CMSC 202, Version 2/02
11
Declaring operator+
As a Non-member Friend
• Declare operator+ as a friend in the class
definition.
class Complex {
public:
friend const Complex
operator+ (const Complex& a,
const Complex& b);
…
};
CMSC 202, Version 2/02
12
Operator+ As a
Non-member Friend (con’t)
const Complex operator+ (const Complex& lhs,
const Complex& rhs) {
Complex sum;
// accessors and mutators not required
sum.imagine = lhs.imagine + rhs.imagine;
// but preferred
sum.setReal( lhs.getReal( ) + rhs.getReal( )) ;
return sum;
} // violates encapsulation! Non-friend better.
CMSC 202, Version 2/02
13
Printing Objects
• Each object should be responsible for
printing itself.
• This guarantees objects are always printed
the same way.
• It allows us to write intuitive output code:
Complex C5 (5, 3);
cout << C5 << endl;
CMSC 202, Version 2/02
14
Operator<<
• The insertion operator << is a function and
can (and should) be overloaded. We can
do operator>>, too.
• << is a binary operator.
• The left-hand operand is of type ostream&
• Therefore, operator<< cannot be a
member function. It must be a nonmember.
CMSC 202, Version 2/02
15
operator<<
ostream&
operator<< (ostream& out, const Complex& c) {
out << c.getReal( );
int imagine = c.getImagine( );
out << (imagine < 0 ? “ - ” : “ + ” )
out << imagine << “i”;
return out;
}
• Could be, and often, is a friend
• Note: no endl
CMSC 202, Version 2/02
16
Operator<<
Returns Type ‘ostream &’
• Why? So we can write statements such as
cout << C5 << “is a complex number”
OR
cout << C3 << endl << C2 << endl;
• << associates from left to right.
CMSC 202, Version 2/02
17
Overloading Unary Operators
Complex C1(4, 5), C2;
C2 = -C1;
is an example of a unary operator (minus).
• We can and should overload this operator
as a member function.
CMSC 202, Version 2/02
18
Unary operatorconst Complex Complex :: operator- ( ) const
{
Complex x;
x.real = -real;
x.imagine = imagine;
return x;
}
CMSC 202, Version 2/02
19
Overloading =
• Remember that assignment performs a
memberwise (shallow) copy by default.
• This is not sufficient when a data member
is dynamically allocated.
• = must be overloaded to do a deep copy.
CMSC 202, Version 2/02
20
Restrictions
• Not all operators can be overloaded.
• You can’t make up your own operators.
• You can’t overload operators for
primitive types (like int).
• You can’t change the precedence of an
operator.
• You can’t change the associativity of an
operator.
CMSC 202, Version 2/02
21
Good Programming Practices
• Overload operators so that they mimic the
behavior of primitive data types.
• Overloaded binary arithmetic operators should
– return const objects by value
– be written as non-member functions when appropriate
to allow commutativity
– be written as non-friend functions (if data member
accessors are available)
• Overload unary operators as member functions.
• Always overload <<
• Always overload = for objects with dynamic
data members.
CMSC 202, Version 2/02
22