Professional C__ - Marc Gregoire [317]
j = +(-i); // Apply unary plus to the result of applying unary minus to i.
j = -(-i); // Apply unary minus to the result of applying unary minus to i.
Code snippet from ArithmeticOperators\SpreadsheetCellTest.cpp
Unary minus negates the operand, while unary plus returns the operand directly. The result of unary plus or minus is not an lvalue; you can’t assign to it. This means you should return a const object when you overload them. However, note that you can apply unary plus or unary minus to the result of unary plus or unary minus. Because you’re applying these operations to a const temporary object, you must make the unary operator- and operator+ themselves const; otherwise, the compiler won’t let you call them on the const temporary.
Here is an example of a SpreadsheetCell class definition with an overloaded unary operator-. Unary plus is usually an identity operation, so this class doesn’t overload it:
class SpreadsheetCell
{
public:
// Omitted for brevity. Consult Chapter 7 for details.
const SpreadsheetCell operator-() const;
// Omitted for brevity. Consult Chapter 7 for details.
};
Code snippet from ArithmeticOperators\SpreadsheetCell.h
Here is the definition of the unary operator-:
const SpreadsheetCell SpreadsheetCell::operator-() const
{
SpreadsheetCell newCell(*this);
newCell.set(-mValue); // call set to update mValue and mStr
return newCell;
}
Code snippet from ArithmeticOperators\SpreadsheetCell.cpp
operator- doesn’t change the operand, so this method must construct a new SpreadsheetCell with the negated value, and return a copy of it. Thus, it can’t return a reference.
Overloading Increment and Decrement
There are four ways to add one to a variable:
i = i + 1;
i += 1;
++i;
i++;
Code snippet from ArithmeticOperators\SpreadsheetCellTest.cpp
The last two are called the increment operators. The first form is prefix increment, which adds one to the variable, then returns the newly incremented value for use in the rest of the expression. The second form is postfix increment, which returns the old (non-incremented) value for use in the rest of the expression. The decrement operators function similarly.
The two possible meanings for operator++ and operator-- (prefix and postfix) present a problem when you want to overload them. When you write an overloaded operator++, for example, how do you specify whether you are overloading the prefix or the postfix version? C++ introduced a hack to allow you to make this distinction: The prefix versions of operator++ and operator-- take no arguments, while the postfix versions take one unused argument of type int.
If you want to overload these operators for your SpreadsheetCell class, the prototypes would look like this:
class SpreadsheetCell
{
public:
// Omitted for brevity. Consult Chapter 7 for details.
SpreadsheetCell& operator++(); // Prefix
SpreadsheetCell operator++(int); // Postfix
SpreadsheetCell& operator--(); // Prefix
SpreadsheetCell operator--(int); // Postfix
// Omitted for brevity. Consult Chapter 7 for details.
};
Code snippet from ArithmeticOperators\SpreadsheetCell.h
The C++ standard specifies that the prefix versions of increment and decrement return an lvalue, so they can’t return a const value. The return value in the prefix forms is the same as the end value of the operand, so prefix increment and decrement can return a reference to the object on which they are called. The postfix versions of increment and decrement, however, return values that are different from the end values of the operands, so they cannot return references.
Here are the implementations of these operators:
SpreadsheetCell& SpreadsheetCell::operator++()
{
set(mValue + 1);
return *this;
}
SpreadsheetCell SpreadsheetCell::operator++(int)
{
SpreadsheetCell oldCell(*this); // Save the current value before incrementing
set(mValue + 1); // Increment
return oldCell; // Return the old value.
}
SpreadsheetCell& SpreadsheetCell::operator--()
{
set(mValue - 1);
return *this;
}
SpreadsheetCell SpreadsheetCell::operator--(int)