Overloading the Increment/Decrement Operators


This explains how to overload the increment and decrement operators. The example involves only the increment operator, but the decrement operator is handled in exactly the same way.

Consider the following definition of a simple Clock class:

class Clock {
    friend ostream& operator<<(ostream& out, Clock& c);
  public:
    Clock(int h=12, int m=0);   // noon by default
    Clock operator++();	        // prefix form; advance clock by 1 min 
    Clock operator++(int);      // postfix form; advance clock by 1 min
  private:
    void tick();                // advance clock by 1 min
    int hour, min;
};
We want to be able to use Clock objects like this:
#include <iostream.h>

int main()
{
  Clock c1, c2(3,20), c3(10,59);

  cout << c1 << " " << c2 << " " << c3 << endl;
  // should output 12:00 03:20 10:59 

  c1++;
  ++c2;
  c3++;

  cout << c1 << " " << c2 << " " << c3 << endl;
  // should output 12:01 03:21 11:00

  c1 = ++c2;
  cout << c1 << " " << c2 << endl;
  // should output 03:22 03:22

  c1 = c3++;
  cout << c1 << " " << c3 << endl;
  // should output 11:00 11:01

  return 0;
}
The constructor and tick() methods are easy:
Clock::Clock(int h, int m) : hour(h), min(m) { }

// Advance the object's min by 1
void Clock::tick()
{
  min = (min + 1) % 60;
  if (min == 0) 
    hour = (hour + 1) % 24;
}
The leftshift operator is also easy:
ostream& operator<<(ostream& os, Clock& c)
{
  if (c.hour < 10)               // then pad the hour with a 0
    os << '0';
  os << c.hour << ":";
  if (c.min < 10)                // then pad the min with a 0
    os << '0';
  os << c.min;
  return os;
}
Ok, now the prefix form of the increment operator. For syntax like:
c1 = ++c2;
we need the c2 object to increment itself first, and then for the resulting object to be assigned to c1. Remember, the righthand side of the assignment is equivalent to c2.operator++().
Clock Clock::operator++()    // prefix form
{
  tick();             // increment
  return *this;       // return itself for assignment
}
Now for the postfix version, i.e., syntax like:
c1 = c3++;
The compiler needs some way to distinguish this method from the prefix form. C++ makes this distinction by requiring the postfix increment operator to take an int argument. There is absolutely no significance to this argument, and in fact it does not even need a name. Think of the "int" as a meaningless symbol that says to the compiler "I am the postfix version of the increment operator." The righthand side of the preceding assignment is equivalent to c3.operator++(int).
Clock Clock::operator++(int)   // parameter ignored and does
{                              // not even need to be named.
  Clock c = *this;  // Save the object.
  tick();           // Increment the object.
  return c;         // Return the object as it was before incrementing.
}


BU CAS CS - Overloading the Increment/Decrement Operators
Web page by Drue Coles <dcoles@cs.bu.edu>