|
Increment / Decrement Operator Overloading (++, --)
In this section, we will study how to overload increment and decrement operators (++ and --). We will study increment
operators in detail and the decrement operators are left for you to implement as practice. There are two types of
increment operators actually: pre-increment and post-increment. So what's the difference, you ask? The following
examples will make it clear.
++x; // Pre-increment operator.
x++; // Post-increment operator.
int y;
y = ++x; // Value of x is incremented, then x is assigned to y.
y = x++; // x is assigned to y, then value of x is incremented.
Since C++ considers them as separate operators, we should overload both of them. We will declare the overloaded functions
as class member functions for this example. The notes for how to do it using global functions are at the bottom of this section.
First, let's overload the pre-increment operator.
class Complex {
private:
double real, imag;
public:
Complex() { real = imag = 0; }
....
Complex& operator++(void); // Pre-increment operator
};
Complex& Complex::operator++(void) {
real++;
imag++;
return *this;
}
int main(void) {
Complex num1(2, 3);
cout << "num1 is " << num1.GetReal() << " + "
<< num1.GetImag() << "i" << endl;
++num1;
cout << "num1 is " << num1.GetReal() << " + "
<< num1.GetImag() << "i" << endl;
return 0;
}
If you've been reading the tutorial from the beginning, the above code should be very easy to understand. We simply increment
the real and imag members of the class and return *this, which is a reference to the object itself. Running this code produces
the expected results:
num1 is 2 + 3i
num1 is 3 + 4i
Now if you try to use num1++; instead of ++num1; in the above code, it will not compile. What is the reason
for this? This is because we haven't overloaded the post-increment operator yet. So let's implement that functionality
as well.
class Complex {
private:
double real, imag;
public:
Complex() { real = imag = 0; }
....
Complex& operator++(void); // Pre-increment operator
Complex operator++(int); // Post-increment operator
};
Complex Complex::operator++(int) {
Complex tmp = *this;
real++;
imag++;
return tmp;
}
Now we've implemented some really funny code here.
As you may have noticed, the post-increment function is declared to accept an int parameter and returns Complex instead of
Complex &. Why does it accept an int parameter? That's how the C++ standards committee decreed that a post-increment overload should look
like (even though num++; doesn't have an int anywhere). You may NOT use any other type (e.g. char, float or double) for the
argument type. Also note that the implementation of the function doesn't really give the int argument a variable name. Since
the int parameter is really a dummy, it doesn't need to be actually named in the function implementation! The value passed for
the int parameter is compiler dependent anyway and this is a case where the existence of the argument is necessary, but its
value doesn't matter!
As to why the
function returns Complex instead of Complex &, this is fairly easy to explain: The post-increment operator is supposed to
return the current value of the object and then increment it. Hence, we store the current value in a temporary
variable, increment the members and then return the temporary variable (which holds the previous value of the object).
You are invited to verify that the following code works correctly:
Complex num1(5,10);
Complex num2;
num1++;
++num1;
num2 = num1++;
num2 = ++num1;
You can also implement pre-increment and post-increment operators as global functions, by declaring them as follows:
Complex& operator++(Complex& num); // Pre-increment
Complex& operator++(Complex& num, int); // Post-increment
Exercises
1. Implement pre-decrement and post-decrement operators for the Complex class.
2. Implement the above as global functions. See the previous section for examples if you have trouble using global functions.
You may need to declare the global functions as friends, if you don't implement SetReal() and SetImag().
|
|