In the March 1994 issue of Borland
C++ Developer's Journal, I believe there's
a line missing from an example program. In Listing B of the article
C++ Language tip - Increment- and decrement-operator overloading
there's no return statement for the overloaded pre-increment
operator member function of the Integer class. You'll
need to add
return (Integer &)intValue;
to the end of the operator++() function.
If you try to compile the code as it appears in the article, the
compiler warns about the function's lack of a return statement.
Strangely, when I run the program without the return statement,
the function displays 1048 instead of 2.
Alan Funk
Houston, Texas
You're right, Alan, there's a line missing from the code's overloaded pre-increment function. As you said, the function should include a return statement.
Before we show the correction, let's talk for a moment about exactly what value an overloaded increment operator should return. In our original article on overloaded increment operators, we overloaded the increment operator for a class that contained integers. In that overloaded increment function, we incorrectly returned an integer value.
Typically, when you call the increment operator for a variable
of a built-in data type, you ignore the return value. For example,
the lines
int i=1; i++;
declare the integer i, then call the increment operator to increment the value of i. However, the lines don't use the increment operator's return value.
The rewritten lines
int i=1, j=0;
j=i++;
declare the variables i and j, increment i, and store the incremented value of i in the variable j. As you can see, the increment operator returns a value that's the same type as the variable you increment.
For this reason, classes that overload the increment (and decrement)
operator should return a value that's the same type as
the incremented object. Continuing with our example, the lines
Circle myCirc(1), anotherCirc; anotherCirc = myCirc++;
declare the two Circle class objects myCirc and anotherCirc, call the Circle class's overloaded increment operator, then store its return value in the anotherCirc object. As you can see, the Circle class's overloaded increment operator should return a Circle object.
In fact, your suggested repair line,
return (Integer &)intValue;
addresses this issue by returning an Integer object reference. However, there's a good reason you shouldn't return the value this way. When you cast the integer data member intValue into an Integer class reference, your program must create a temporary Integer class object to store this reference variable. To create the temporary object, your program must call the Integer class constructor, which is typically inefficient.
So how can overloaded pre-increment functions return reference variables that are references to objects of the class? Quite simply, they can use the this pointer.
Remember, to call the pre-increment operator, you specify an object of the class. Inside the pre-increment operator function, you have access to that object through the this pointer. By simply returning the incremented object's data, the function returns a reference to that object.
Listing A contains the corrected version of the Integer class in the PREPOST.CPP file. Notice the new return statement at the bottom of the overloaded pre-increment function in the Integer class definition.
Listing A: Corrected Integer class from PREPOST.CPP
class Integer { public: Integer(int newValue = 0) : intValue(newValue) {} Integer& operator++() { cout << "Pre-increment\n"; ++intValue; return *this; //add this line } Integer operator++(int) { cout << "Post-increment\n"; Integer temp(*this); ++(*this); return temp; } operator int() const { return intValue; } private: int intValue; };
By the way, if a function doesn't return a value, you'll
almost always get strange return values when you call the function.
Exactly what value an errant function returns depends on what's
on the stack or in the AX register when the function exits.
Copyright (c) 1996 The Cobb Group, a division of Ziff-Davis Publishing Company. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of Ziff-Davis Publishing Company is prohibited. The Cobb Group and The Cobb Group logo are trademarks of Ziff-Davis Publishing Company.