Operator overloading -- Lecture notes

Unary operators

Examples: unary minus and & ("address of")
class X {
  X operator-() const;
  X operator&() const;
};

class Y {
  friend Y operator- (const Y & );
  friend Y operator& (const Y & );
};

Another important unary operator is logical negation, operator !.

Binary operators

Examples: binary plus and & ("bitwise and")
class X {
  X operator+( const X& ) const;
  X operator&( const X& ) const;
};

class Y {
  friend Y operator+ (const Y &, const Y & );
  friend Y operator& (const Y &, const Y & );
};
In general, it is not necessary to have the non-member functions as friends, but if any of the private data members of the operands needs to be accessed, this is a necessity.

Binary operators are usually defined as friends (non-members), for symmetry. This is recommended for commutative operators such as arithmetic operators. Unary operators are usually represented as members.

Adapted from Paul J. Lucas, "The C++ Programmer's Handbook", AT & T


Example: * for strings

The following example shows how operator * can be defined for strings. Notice that a string literal like "hello" is not of type string in C++, but of type char * and is stored as a zero-terminated array of characters, with the zero character at the end, i.e. as 'h', 'e', 'l', 'l', 'o', '\0' .

Operators cannot be redefined for built-in types in C++, so we cannot make "hello" * 3 work -- that would require defining operator* ( char *, int ), but neither of the two arguments is of a class type. Still, we can make it work a variable of type string and an int:

#include <iostream.h>
#include <string>

string operator*( const string& s, int n ){
  string res = "";
  for( int i=0; i < n; i++ )
     res += s;
  return res;
}

int main(){
  string s = "hello";
  cout << s * 3 << endl;
  return 0;
}
which prints "hellohellohello", as we wanted.

A class for Fractions

Overloaded operators return as results new objects (instances of the class). These objects are mostly temporaries and get destroyed very soon. The following example demonstrates how arithmetic operators can be defined for a class representing a fraction. It also shows, by making constructors and destructors print special messages, how and when objects are created and destroyed.

Sources:

The output of running main_frac.cpp follows. Notice the calls to destructor that show when temporaries returned by overloaded operators get destroyed. The order in which things happen is completely determined at compile time, so all calls to the destructor were inserted by the compiler into the executable at the corresponding places.

Exercises:

  1. Simplify fractions after operations. Notice that 144/144 is actually 1/1 i.e. just 1. You will need a function for finding the G.C.D. (greatest common divisor) of the numerator and the denominator of a fraction (so that you can divide both by that G.C.D., resulting in the simplified fraction)
  2. Implement other arithmetic operations, including the unary minus.
  3. Print fractions that are really integers (like 3/1) naturally, i.e. without the denominator and slash.
Test 1:

myFrac other constructor called
myFrac other constructor called
myFrac default constructor called
myFrac other constructor called
operator= for myFrac
myFrac destructor called
1/2 + 1/3 = 5/6

Test 2:

myFrac copy constructor called
myFrac other constructor called
1/4
myFrac destructor called

Test 3:

myFrac other constructor called
myFrac other constructor called
myFrac other constructor called
 x = 2/5
 y = 5/1
 z = 3/1

Test 4:

myFrac other constructor called
myFrac other constructor called
myFrac other constructor called
144/144
myFrac destructor called
myFrac destructor called
myFrac destructor called

Test 5:

myFrac other constructor called
myFrac other constructor called
myFrac destructor called
3/2

That's All Folks! Time to destroy variables...
myFrac destructor called
myFrac destructor called
myFrac destructor called
myFrac destructor called
myFrac destructor called
myFrac destructor called
myFrac destructor called
myFrac destructor called