Recall that there are two versions of ++: the prefix version, which is written as ++x, and the postfix version, which is written as x++. We will start with the prefix version as it is the simpler of the two to implement.
What does ++x do? Well, it increments x to the next value. This of course can be a numeric valueβgiven int x = 3; we can use ++x to increase it to 4. But βincrementβ can have non-numeric meanings. When used on an iterator, the ++ operator advances the iterator to the next item in the collection. In fact, we can write a loop to walk through a vector using an iterator and ++:
vector<int> v = {1, 2, 3, 4, 5};
// Get an iterator that points to the first item
vector<int>::iterator it = v.begin();
while (it != v.end()) {
++it; // advance the iterator to the next item
int current = *it; // get the value at the current iterator position
cout << current << endl;
}
For this code to work, there must be a definition for what ++ means for the iterator. This definition is provided by an overload for the operator.
To write a custom ++ operator, we need to figure out what parameters and return type it needs. The ++ does not need to operate on any data other than the object it is called on, so we do not need a parameter. We do need a return value however. In addition to incrementing the current value, ++ needs to return the updated value so that we can use it in a complex expression like y = ++x. This means the prototype of ++ should look like:
Note that the return type is a reference to a Rational. If the return type was void, we would not be able to use ++r1 in a larger expression, such as r2 = ++r1;. In that case, r2 = ++r1; would turn into r2 = (nothing); once ++ executed. If the return type was Rational, we would return a copy of the modified object. That would be inefficient. (And it would prevent code like ++(++r1) from being able to change r1 twice.) So the return type is Rational&β a reference, not copy, to the updated object.
Note how the object returns itself: return *this;. Recall that this is the memory address of the current object. *this dereferences that pointer to get the actual Rational object which we then return as a copy. Again, the math is not of critical importance, but you should take a minute to confirm that the right way to add one to a fraction is to increase the numerator by the value of the denominator.
Define the operator-- for Rational. Itβs logic should be the same as ++ but it should decrease the value by 1 instead of increasing it. (Decrease the numerator by the value of the denominator.)