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 <iostream> #include <cstdlib> #include <cmath> 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:
  1. The function operator+ is not a member function of the Money class.
    How can you tell? Can it be? Should it be?

  2. Since it's not a member function, accessors must be used.
    What if there were no accessors?

  3. Both function parameters are Money objects passed by const reference.
    Why? Should other parameter types be permitted?

  4. 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 <iostream> #include <cstdlib> #include <cmath> 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