The basics of Operator Overloading
One interesting application of function overloading is
operator overloading. Operators such as +, -, == and <<, etc.
are really function calls with a different syntax.
Thinking about integers
When we write code such as
int x, y;
y = x + 7;
the "+" operator is really like a function which takes two arguments
x and 7. The "+" operator returns a
single value which is the sum of the arguments (usually called operands).
We could just as easily written functions (e.g Add(), Plus())
to add the integers.
Operators such as +, -, ==, and <<, etc. will make sense for
many (but not all) classes we design. For example, consider the class below
#include
#include
#include
using namespace std;
// Class for amounts of money in U.S. currency.
// Text display 8.1 (part 1), page 304
// Modified for CMSC 202 coding standards
class Money
{
public:
Money( );
Money(double amount);
Money(int theDollars, int theCents);
Money(int theDollars);
double GetAmount( ) const;
int GetDollars( ) const;
int GetCents( ) const;
// Input() reads the dollar sign as well as the amount number.
void Input( );
void Output( ) const;
private:
//A negative amount is represented as negative dollars and
//negative cents. Negative $4.50 is represented as -4 and -50
int m_dollars;
int m_cents;
int DollarsPart(double amount) const;
int CentsPart(double amount) const;
int Round(double number) const;
};
It makes sense to want add two Money objects together as in this code fragment
Money total, popcorn, candy;
// get popcorn sales amount
cout << "Enter the amount of the popcorn sales: ";
popcorn.Input( );
// get candy sales amount
cout << "Enter the amount of the candy sales: ";
candy.Input( );
// output total sales
total = popcorn + candy;
total.Output( );
cout << endl;
How can the compiler/linker know what the line total = popcorn + candy;
means? We tell them by creating a function that adds two Money objects.
The name of that function is operator+.
operator+ for the Money class
Let's take a closer look at Money's operator+ function.
Its prototype is
const Money operator+ (const Money& amount1, const Money& amount2);
This function is not a member of the Money class -- it's an "ordinary"
function that has Money objects as parameters.
The prototype is found in Money.h, but outside the class definition.
The implementation of operator+ is shown below
// Money's operator+ as a non-member function
const Money operator+ (const Money& amount1, const Money& amount2)
{
int allCents1 = amount1.GetCents( ) + amount1.GetDollars( ) * 100;
int allCents2 = amount2.GetCents( ) + amount2.GetDollars( ) * 100;
int sumAllCents = allCents1 + allCents2;
// use abs() in case of negative money
int absAllCents = abs(sumAllCents);
int finalDollars = absAllCents / 100;
int finalCents = absAllCents % 100;
if (sumAllCents < 0)
{
finalDollars = -finalDollars;
finalCents = -finalCents;
}
return Money(finalDollars, finalCents);
}
Notes and questions:
- The function operator+ is not a member function of the Money class.
How can you tell? Can it be? Should it be?
- Since it's not a member function, accessors must be used.
What if there were no accessors?
- Both function parameters are Money objects passed by const reference.
Why? Should other parameter types be permitted?
- The function returns a const Money object by value.
Why by value? Why const? Let's examine this more closely.
Returning by const value
Consider this declaration
Money m1(4, 50), m2(5, 25);
The expression (m1 + m2) is an unnamed Money object that represents the
sum of m1 and m2 which is returned by operator+.
It's possible to write code like this
(m1 + m2).Ouput();
By having operator+ return by const value, we allow the code
above, but prohibit this code
(m1 + m2).Input( );
since Input( ) is a non-const member function. Having operator+
return by const value (rather than just by value) prevents us from inadvertently
changing the returned object through the use of non-const member functions.
But what about this code?
Money m1(4, 50), m2(5, 25), m3;
m3 = (m1 + m2);
m3.Input( ); // is this legal?
Money's operator+ as a member function
Here's a new version of the Money class in which operator+
is defined as member function.
#include
#include
#include
using namespace std;
// Class for amounts of money in U.S. currency.
// Text display 8.2 (part 1), page 315
// Modified for CMSC 202 coding standards
class Money
{
public:
Money( );
Money(double amount);
Money(int theDollars, int theCents);
Money(int theDollars);
double GetAmount( ) const;
int GetDollars( ) const;
int GetCents( ) const;
// Input() reads the dollar sign as well as the amount number.
void Input( );
void Output( ) const;
const Money operator+ ( const Money& amount2) const;
private:
//A negative amount is represented as negative dollars and
//negative cents. Negative $4.50 is represented as -4 and -50
int m_dollars;
int m_cents;
int DollarsPart(double amount) const;
int CentsPart(double amount) const;
int Round(double number) const;
};
// Money's operator+ as a member function
const Money Money::operator+ (const Money& amount2) const
{
int allCents1 = m_cents + m_dollars * 100;
int allCents2 = amount2.m_cents + amount2.m_dollars * 100;
int sumAllCents = allCents1 + allCents2;
// use abs() in case of negative money
int absAllCents = abs(sumAllCents);
int finalDollars = absAllCents / 100;
int finalCents = absAllCents % 100;
if (sumAllCents < 0)
{
finalDollars = -finalDollars;
finalCents = -finalCents;
}
return Money(finalDollars, finalCents);
}
Notice that operator+ has just one parameter instead of two.
When operator+ is defined as a member function, the calling object
serves as the first parameter. Consider what happens in this code fragment
Money m1(4, 50), m2(5, 25), m3;
m3 = (m1 + m2);
m1 is the calling object and m2 is the single parameter.
The expression m1 + m2 is equivalent to m1.operator+( m2 ).
What effect does returning by const value have on this code?
Is the statement m3.Input( ); valid or illegal?
Notice also that since this is a member function, there is no need for accessors.
Should accessors be used anyway?
operator+ is a const member function.
Why is this a good idea?
So, given that operators can be overloaded as member or non-member functions,
which is best? A good question.
Last Modified: Monday, 28-Aug-2006 10:15:53 EDT