Overloading the Increment and Decrement Operators

Problem

You have a class where the familiar increment and decrement operators make sense, and you want to overload operator++ and operator-- to make incrementing and decrementing objects of your class easy and intuitive to users.

Solution

Overload the prefix and postfix forms of ++ and -- to do what you want. Example 8-14 shows the conventional technique for overloading the increment and decrement operators.

Example 8-14. Overloading increment and decrement

#include 

using namespace std;

class Score {
public:
 Score( ) : score_(0) {}
 Score(int i) : score_(i) {}

 Score& operator++( ) { // prefix
 ++score_;
 return(*this);
 }
 const Score operator++(int) { // postfix
 Score tmp(*this);
 ++(*this); // Take advantage of the prefix operator
 return(tmp);
 }
 Score& operator--( ) {
 --score_;
 return(*this);
 }
 const Score operator--(int x) {
 Score tmp(*this);
 --(*this);
 return(tmp);
 }
 int getScore( ) const {return(score_);}

private:
 int score_;
};

int main( ) {
 Score player1(50);

 player1++;
 ++player1; // score_ = 52
 cout << "Score = " << player1.getScore( ) << '
';
 (--player1)--; // score_ = 50
 cout << "Score = " << player1.getScore( ) << '
';
}

 

Discussion

The increment and decrement operators often make sense for classes that represent some sort of integer value. They are easy to use, as long as you understand the difference between prefix and postfix and you follow the conventions for return values.

Think about incrementing an integer. For some integer i, there are two ways to do it with the ++ operator:

i++; // postfix
++i; // prefix

Both increment i: the first version creates a temporary copy of i increments i, then returns the temporary value, the second increments i then returns it. C++ allows operator overloading, which means you can make your favorite user-defined type (a class or an enum) behave like an int in this regard.

Overload operator++ and operator-- to get what you want. Example 8-14 illustrates how to overload both the prefix and postfix versions:

Score& operator++( ) { // prefix
 ++score_;
 return(*this);
}
const Score operator++(int) { // postfix
 Score tmp(*this);
 ++(*this);
 return(tmp);
}

Prefix appears as you would expect, but for the compiler to distinguish between the two, an int parameter is included as part of the postfix operator declaration. It has no semantic use; at runtime, it is always passed as zero so you can ignore it.

Once you do this, you can use the Score class as you would an int:

Score player1(50);

player1++;
++player1; // score_ = 52

You probably noticed that the signatures for the prefix version of operator++ return a reference to the current class. You should do this (instead of, say, returning void) so that the object that is being incremented or decremented can be used in other expressions. Consider this line from the example:

(--player1)--;

Strange, yes, but it illustrates a point. If prefix operator-- didn't return anything meaningful, then this expression would not compile. Another example would be a function call:

foo(--player1);

The function foo expects an argument of type Score, and that's exactly what you have to return from prefix operator-- for this to compile.

Operator overloading is a powerful feature that lets you use the same operators on user-defined types that you would on built-in types. Proponents of other languages that do not allow operator overloading bemoan the potential for confusion and complexity, and admittedly, lots of operators can be overloaded for any kind of custom behavior. But when it comes to simple increment and decrement, it's nice to be able to customize your classes' behavior to your liking.

See Also

Recipe 8.14

Building C++ Applications

Code Organization

Numbers

Strings and Text

Dates and Times

Managing Data with Containers

Algorithms

Classes

Exceptions and Safety

Streams and Files

Science and Mathematics

Multithreading

Internationalization

XML

Miscellaneous

Index



C++ Cookbook
Secure Programming Cookbook for C and C++: Recipes for Cryptography, Authentication, Input Validation & More
ISBN: 0596003943
EAN: 2147483647
Year: 2006
Pages: 241

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net