The unary operators are shown in Table 12.4.
Table 12.4 Redefinable Unary Operators
Operator | Name |
! | Logical negation |
& | Address-of |
* | Pointer dereference |
+ | Unary Plus |
++ | Increment |
– | Unary negation |
–– | Decrement |
Of the operators shown in Figure 12.4, the postfix increment and decrement operators (++ and ––) are treated separately in “Increment and Decrement”.
To declare a unary operator function as a nonstatic member, it must be declared in the form:
ret-typeoperatorop()
where ret-type is the return type, and op is one of the operators listed in Table 12.4.
To declare a unary operator function as a global function, it must be declared in the form:
ret-type operatorop( arg )
where ret-type and op are as described for member operator functions, and the arg is an argument of class type on which to operate.
Note:
There is no restriction on the return types of the unary operators. For example, it makes sense for logical negation (!) to return an integral value, but this is not enforced.
The increment and decrement operators fall into a special category because there are two variants of each:
Preincrement and postincrement
Predecrement and postdecrement
When you write overloaded operator functions, it can be useful to implement separate versions for the prefix and postfix versions of these operators. To distinguish between the two, the following rule is observed: the prefix form of the operator is declared exactly the same way as any other unary operator; the postfix form accepts an additional argument of type int.
Important:
When specifying an overloaded operator for the postfix form of the increment or decrement operator, the additional argument must be of type int; specifying any other type generates an error.
The following example shows how to define prefix and postfix increment and decrement operators for the Point class:
class Point
{
public:
// Declare prefix and postfix increment operators.
Point& operator++(); // Prefix increment operator.
Point& operator++(int); // Postfix increment operator.
// Declare prefix and postfix decrement operators.
Point& operator—(); // Prefix decrement operator.
Point& operator—(int); // Postfix decrement operator.
// Define default constructor.
Point() { _x = _y = 0; }
// Define accessor functions.
int x() { return _x; }
int y() { return _y; }
private:
int _x, _y;
};
// Define prefix increment operator.
Point& Point::operator++()
{
_x++;
_y++;
return *this;
}
// Define postfix increment operator.
Point& Point::operator++(int)
{
_x++;
_y++;
return *this;
}
// Define prefix decrement operator.
Point& Point::operator—()
{
_x—;
_y—;
return *this;
}
// Define postfix decrement operator.
Point& Point::operator—(int)
{
_x—;
_y—;
return *this;
}
The same operators can be defined in file scope (globally) using the following function heads:
friend Point& operator++( Point& ) // Prefix increment
friend Point& operator++( Point&, int ) // Postfix increment
friend Point& operator—( Point& ) // Prefix decrement
friend Point& operator—( Point&, int ) // Postfix decrement
The argument of type int that denotes the postfix form of the increment or decrement operator is not commonly used to pass arguments. It usually contains the value 0. However, it can be used as follows:
class Int
{
public:
Int &operator++( int n );
private:
int _i;
};
Int& Int::operator++( int n )
{
if( n != 0 ) // Handle case where an argument is passed.
_i += n;
else
_i++; // Handle case where no argument is passed.
return *this;
}
...
Int i;
i.operator++( 25 ); // Increment by 25.
No syntax exists for using the increment or decrement operators to pass these values other than explicit invocation, as shown in the preceding code. A more straightforward way to implement this functionality is to overload the addition/assignment operator (+=).