Operator Overloading  «Prev  Next»
Lesson 17

Overloading Operators in C++ Conclusion

In this module the basics of overloading operators were discussed.
You also have a grasp of how to build a non-native type with a consistent and complete interface. In particular, you learned:
  1. Why operator overloading is useful in C++
  2. Which operators can be overloaded
  3. How and when to use friend functions to access class members
  4. How to overload unary operators
  5. How to overload binary operators
  6. How to overload input and output operators
  7. How to overload the member pointer operator
  8. How to overload the new and delete operators

C++ Operator Overloading Guidelines

In C++ you can give special meanings to operators, when they are used with user-defined classes and this is called operator overloading. You can implement C++ operator overloads by providing special member-functions on your classes that follow a particular naming convention. For example, to overload the + operator for your class, you would provide a member-function named operator+ on your class.
The following set of operators is commonly overloaded for user-defined classes:
  1. = (assignment operator)
  2. + - * (binary arithmetic operators)
  3. += -= *= (compound assignment operators)
  4. == != (comparison operators)
Here are some guidelines for implementing these operators. These guidelines are very important to follow.

Assignment Operator =
The assignment operator has a signature like this:
 class MyClass {
 public:
   ...
   MyClass & operator=(const MyClass & rhs);
   ...
 }

 MyClass a, b;
 ...
 b = a;   // Same as b.operator=(a);

Notice that the = operator takes a const-reference to the right hand side of the assignment. The reason for this should be obvious, since we don't want to change that value; we only want to change what is on the left hand side. Also, you will notice that a reference is returned by the assignment operator. This is to allow operator chaining. You typically see it with primitive types, like this:
int a, b, c, d, e;
a = b = c = d = e = 42;

This is interpreted by the compiler as:
a = (b = (c = (d = (e = 42))));

In other words, assignment is right-associative. The last assignment operation is evaluated first, and is propagated leftward through the series of assignments. Specifically: e = 42 assigns 42 to e, then returns e as the result
  1. The value of e is then assigned to d, and then d is returned as the result
  2. The value of d is then assigned to c, and then c is returned as the result
Now, in order to support operator chaining, the assignment operator must return some value. The value that should be returned is a reference to the left-hand side of the assignment.
Notice that the returned reference is not declared const. This can be a bit confusing, because it allows you to write crazy stuff like this:
 MyClass a, b, c;
 ...
 (a = b) = c;  //

At first glance, you might want to prevent situations like this, by having operator= return a const reference. However, statements like this will work with primitive types.
It is important to return a non-const reference from your operator=.
General Rule: If it is good enough for ints, then it is good enough for user-defined data-types.