Overview of Operator Overloading

Overview of Operator Overloading

Introduction

Until now, we have mostly performed manipulations on objects by calling member functions of the objects. This member function-call notation is cumbersome for certain kinds of classes (such as mathematical classes). Also, many common manipulations in C++ are typically performed with operators (e.g., input and output, comparisons, etc.).

We can use C++’s large set of built-in operators to specify common object manipulations. Enabling C++’s operators to work with objects is called operator overloading.

We have already used a couple of overloaded operators. For example, operator << is used for multiple purposes in C++: as the stream-insertion operator and as the left-shift operator. Similarly, >> is also overloaded; it is used both as the stream-extraction operator and as the right-shift operator.

Fundamentals of Operator Overloading

C++ enables the programmer to overload most operators to be sensitive to the context in which they are used. The compiler generates an appropriate function or member function call based on the operator’s use.

To overload an operator, write a function definition; the function name must be the keyword operator followed by the symbol for the operator being overloaded.

To use an operator on class objects, that operator must be overloaded – with two exceptions. The assignment operator (=) may be used with two objects of the same class to perform a default memberwise assignment without overloading. The address operator (&) can can be used with objects of any class without overloading; it returns the address of the object in memory.

The point of operator overloading is to provide the same concise expressive power for user-defined data types that C++ provides with its rich collection of operators that work on built-in types.

Operator overloading is not automatic – the programmer must write operator overloading functions to perform the desired operations. Sometimes these functions are best made member functions; sometimes they are best as friend functions.

Restrictions on Operator Overloading

Here is the list of C++ operators that can be overloaded:

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

There are a handful of C++ operators that cannot be overloaded:

.
.*
::
?:

Some other restrictions that apply:

  • The precedence and associativity of an operator (i.e., whether the operator is applied right-to-left or left-to-right) cannot be changed by overloading. Parentheses can be used to force the order of evaluation of overloaded operators in an expression.

  • It is not possible to change the number of operands that an operator takes: overloaded unary operators remain unary operators, overloaded binary operators remain binary operators. C++’s only ternary operator, ?:, cannot be overloaded.

  • It is not possible to define new operator symbols for new operators; only the existing operators can be overloaded.

  • The meaning of how an operator works on built-in data types cannot be changed by overloading. The programmer cannot, for example, change the meaning of how + adds two integers. Operator overloading works only with objects of user-defined types (i.e. classes or structs) or with a mixture of an object of a user-defined type and and a built-in type.

  • There is no implicit overloading. Overloading an operator such as + does not automatically overload +=.

Overloaded Operators as Standalone Functions vs. Member Functions

The C++ standard specifies that overloaded operators (), [], -> and any assignment operator must be member functions of the class for which they are overloaded.

For operators other than those, overloaded operator functions can be member functions or standalone functions that are not part of a class.

When an operator function is implemented as a member, the leftmost operand must be a class object (or a reference to a class object) of the operator’s class.

If the left operand of an overloaded operator is an object of a C++ standard library class or is not an object at all, then the operator function must be implemented as a standalone function. A standalone operator function is usually made a friend of the class to improve performance by avoiding the overhead of calls to accessor and mutator methods.