Fall 2005
Monday 5:00 - 6:00 Rm 643E, Wednesday 3:00 - 5:00 Rm 621E
C++ allows not only functions and function members to be overloaded, but also allows operators to be overloaded. That is to say, the programmer can define what an operator applied to an object or multiple objects of a given class should do when applied to such objects. The only rule is that the syntax of the operator according to the C++ grammar can not be arbitrary. What this means is that binary operators must remain binary operators and unary operators (e.g., "!") must remain unary operators. Any mathematical operator, the assignment operators (e.g., "=", "+=", etc.), logical operators, and others can be overloaded. Sometimes it is useful to overload "<<" so that it is easier to display information about an object of a class to the standard output stream. There are a few operators that can not be overloaded, including the scope resolution operator "::", the member operator ".", and the "sizeof" operator.
Operators are overloaded with functions whose name starts with "operator" followed by the operator itself. There are two ways to write such functions. One way is to do it external to the class definition. Then, for binary operators, there will be two parameters with types matching the operands to the left and right of the operator. The other way to do it is to place the function declaration or definition inside the class definition of the left operand (i.e., make it a member function of the class). In this case, the operand to the left of the operator is the object through which the member function is called, and there will be one less parameter.
Especially when an operator overload function is defined outside the class, it is sometimes useful to give these functions special permission to access private member variables of the class. This can be done by specifying these functions to be "friends" of the class. Inside the class definition (in either a private or public part of the class, it doesn't matter), the function is declared to be a friend by using the keyword "friend" followed by a specification of the function (which looks the same as a declaration of the function). You must make sure that the parameter types and return type in the friend statement match those in the function header of the operator function exactly, or the compiler will not give the function permission to see the private variables. Any function (not just operator functions) can be declared as friends of a class, and the same function may be a friend to multiple classes (since it is not actually part of these classes). You are also allowed to make a member function of one class a friend of another class.
When an assignment operator is overloaded, it is common to have the function return a reference to the leftmost operand (the variable whose value is changing) so that multiple assignments that are part of the same statement, e.g. "(a = b) = c", will have the correct effect. If the function is declared as part of the class, this can be done by returning "*this"; otherwise, it can be done by returning the first parameter; either way, the return type must be a reference to the correct class. For other types of operators, it is sometimes it is more efficient to make the parameters themselves constant references, so that, at runtime, time and memory are not wasted making copies of the operands that will not be changed anyway. (It is generally a bad idea to make the parameters references that are not constant, because then you can not pass in temporary values such as constants, unless you are dealing with an assignment operator of some sort, in which case you clearly have to declare the first parameter as a non-constant reference if the operator function is not part of the class.)
Some operators (e.g., "=") exist by default for a class even if you do not overload them. As mentioned in the summary for the previous topic, overloading the "=" operator is not the same as overloading the copy constructor which must be done separately (as discussed in lectures). The default behavior for these may not work the way you want, especially for cases in which the class contains pointers (unless you want different objects to point to the same memory). Remember, when dealing with pointers and dynamic memory allocation in C++, it is better to use "new" and "delete" (or "new[]" and "delete[]") instead of "malloc" and "free". Finally, when overloading an assignment operator, you may need a special check to handle the case when the same variable is used as both operands (e.g., "x = x;").