Rules of Operator Overloading

You can overload any of the following operators:

Table 8.1 Overloadable Operators

          ,  
+ - * / % ^ & , |  
~ ! , = < > <= >=
++ -- << >> == != , && ||  
+= -= *= /= %= ^= , &= |=  
<<= >>= [ ] ( ) -> ->* new delete

The last two operators, new and delete, are the free store operators, which were described in Chapter 5. The last operator before those (->*) is the pointer-to-member operator, which is described in Chapter 5 of the C++ Language Reference.

Certain operators can be used as either a binary or a unary operators. For example, the - operator means subtraction when used as a binary operator and negation when used as a unary operator. You can overload such operators to have different meanings in their different usages.

You can use overloaded operators in ways that, if they were not overloaded, would be meaningless. Consider the following expression:

cout << "Hello";

If the << operator were not overloaded, this expression would left-shift cout a number of bits equal to the value of the pointer to the string. The compiler would generate a run-time error when trying to execute this statement. But the statement is syntactically legal, so you can write an overloaded operator function that executes when this statement appears. (For information on overloading the << and >> operators to make your classes work with streams, see Chapter 18, “The Fundamentals of iostream Programming,” in the Class Libraries User's Guide.)

There are a number of restrictions on operator overloading:

You cannot extend the language by inventing new operators. For example, you cannot create your own “exponentiation” operator using the characters **. Those characters do not form a legal operator in C or C++ and you cannot make them one. You must limit yourself to existing operators.

You cannot change an operator's arity, that is, the number of operands that it takes. For example, the logical-NOT operator (~) is a unary operator, meaning that it takes one operand. You cannot use it as a binary operator for built-in types, so you cannot overload it to act as a binary operator for your class. For example:

a = ~b; // Legal

a = b ~ c; // Error

You cannot change an operator's precedence. For example, the multiplication operator has a higher precedence than the addition operator, so the multiplication is performed first when the following expression is evaluated:

a = b + c * d; // Same as a = b + (c * d);

You cannot overload the * and + operators in such a way that the addition is performed first. You must use parentheses to alter the order of evaluation. For example:

a = (b + c) * d; // Parentheses control evaluation

One consequence of this is that the operator you choose may not have the precedence appropriate for the meaning you give it. For example, the ^ operator might seem an appropriate choice to perform exponentiation, but its precedence is lower than that of addition, which could confuse people using it.

You cannot change an operator's associativity. When an operand is between two operators that have the same precedence, it is grouped with one or the other depending on its associativity. For example, the addition and subtraction operators are both left-associative, so the following expressions is evaluated from left to right:

a = b + c - d; // Same as a = (b + c) - d;

You cannot overload the + and - operators in such a way that the subtraction is performed first. You must use parentheses to alter the order of evaluation. For example:

a = b + (c - d); // Parentheses control evaluation

You cannot change the way an operator works with built-in data types. For example, you cannot change the meaning of the + operator for integers.

You cannot overload the following operators:

Operator Definition

. class member operator
.* pointer-to-member operator
:: scope resolution operator
?: conditional expression operator

C++ lets you overload any of the other operators. However, just because you can overload an operator doesn't necessarily mean it's a good idea.