Operator Overloading  «Prev  Next»
Lesson 6 The operator keyword
Objective Use the Operator Keyword to overload Operators

Overload Existing Operators C++

To overload operators, you use the operator keyword similarly to how you used it to overload functions.
For example:
class foo {
public:
foo  operator-();      //overload unary minus
foo  operator-(int);   //binary minus foo-int
foo  operator-(foo);   //binary minus foo-foo
};

foo operator-(int, foo);   //binary minus int-foo
foo operator-(int, foo*);  //illegal:need foo or foo&

Figure 3-6: Operators that can be overloaded
Figure 3-6: Operators that can be overloaded.

Figure 3-7: Operators that cannot be overloaded.
Operators that cannot be overloaded
. .* :: ?:

Precedence, Associativity and Number of Operands

The precedence of an operator cannot be changed by overloading. This can lead to strange situations in which an operator is overloaded in a manner for which its fixed precedence is inappropriate. However, parentheses can be used to force the order of evaluation of overloaded operators in an expression. The associativity of an operator (i.e., whether the operator is applied right-to-left or left-to-right) cannot be changed by overloading. It is not possible to change the "arity" of an operator (which is the number of operands an operator takes):
Overloaded unary operators remain unary operators; overloaded binary operators remain binary operators.
C++'s only ternary operator (?:) cannot be overloaded. Operators &, *, + and - all have both unary and binary versions; these unary and binary versions can each be overloaded.

Notice that it is our style to omit spaces between the keyword operator, the operator to be overloaded, and the signature.
Overloadable operators
+    -    *    /    =    <    >    +=   -=   *=   /=   <<   >>
<<=  >>=  ==   !=   <=   >=   ++   --   %    &    ^    !    |
~    &=   ^=   |=   &&   ||   %=   []   ()   ,    ->*  ->   new 
delete    new[]     delete[]

Operator conversion

The second way to produce automatic type conversion is through operator overloading. You can create a member function that takes the current type and converts it to the desired type using the operator keyword followed by the type you want to convert to. This form of operator overloading is unique because you do not appear to specify a return type.
The return type is the name of theoperator you are overloading. Here is an example:

//: C12:OperatorOverloadingConversion.cpp
class Three {
 int i;
 public:
  Three(int ii = 0, int = 0) : i(ii) {}
};
class Four {
 int x;
 public:
  Four(int xx) : x(xx) {}
  operator Three() const { return Three(x); }
};
void g(Three) {}
 int main() {
 Four four(1);
 g(four);
 g(1); // Calls Three(1,0)
} ///:~
With the constructor technique, the destination class is performing the conversion, but with operators, the source class performs the conversion. The value of the constructor technique is that you can add a new conversion path to an existing system as you are creating a new class. However, creating a single-argument constructor always defines an automatic type conversion (even if it has more than one argument, if the rest of the arguments are defaulted), which may not be what you want (in which case you can turn it off using explicit). In addition, there is no way to use a constructor conversion from a user-defined type to a built-in type; this is possible only with operator overloading.