Operator Overloading in C++

Operator-Overloading-in-C-Feature-Image.jpg

Operator overloading in C++ is done by programmers to redefine the standard operators without changing their original meaning, which enhances code reusability, readability, and efficiency. Also, it helps in performing operations on complex numbers and custom memory management.

In this operator overloading tutorial, we will discuss operator overloading in C++, types of overloading in C++, the difference between function overloading and operator overloading, rules and idioms for the operator overloading, operators that can be overloaded and that cannot be, binary and unary operator overloading, advantages and disadvantages of operator overloading, and important points to remember about the operator overloading in C++.

Table of Contents:

What is Operator Overloading in C++

Operator overloading in C++ is a basic feature that helps programmers define custom behavior for the C++ operators when they are used with user-defined data types such as classes and structures. It helps the programmers by enabling objects to be manipulated by using the standard C++ operators just as the built-in data types.

Syntax of Operator Overloading in C++

return_type ClassName::operator op (parameter_list) {
// Operator overloading implementation
}

Example:

Cpp

Output:

Syntax of Operator Overloading in C++ Output

The code shows the operator overloading in C++, as the + operator is redefined to add two Complex objects by using the overloaded operator + function. This is a common example that shows how to overload operators in C++.

Why Use Operator Overloading in C++?

Below are a few reasons why operator overloading in C++ can be used:

  • Operator overloading in C++ improves performance, code readability, and usability.
  • It allows custom data types to behave like the built-in data types in C++.
  • It also helps to simplify the complex expressions with the user-defined objects.

Types of Overloading in C++

Types of Overloading in C++

There are two types of overloading in C++:

  1. Function Overloading
  2. Operator Overloading

Function Overloading in C++

Function overloading in C++ allows multiple functions to have the same name but different parameters, and the compiler determines which function should be called based on the number and types of arguments.

Example:

Cpp

Output:

Function Overloading in C++ Output

The code shows the function overloading in C++, as in the code, there are multiple add functions with the same name but different parameters, and the compiler will select the function that will be passed to the function calls based on the number and types of arguments.

Note: We have already discussed operator overloading in C++ above, so please refer to that.

Difference Between Function Overloading and Operator Overloading in C++

Feature Function Overloading Operator Overloading
Definition Defining multiple functions with the same name but different parameter lists. Redefining the behavior of C++ operators (+, -, *, etc.) for user-defined types.
Purpose Improves code readability by using the same function name for different tasks. Allows C++ operators to work with objects of custom classes.
Usage Used to perform different operations using the same function name but with different arguments. Used to perform operations on user-defined types (objects) using standard operators.
Syntax int add(int a, int b);
double add(double a, double b);
Complex operator+(const Complex &c);
Implementation Implemented by defining multiple functions with the same name but different parameter lists. Implemented by defining an operator function inside or outside the class.
Return Type The return type does not differentiate overloaded functions. The return type can be different depending on the operator.
Works on Only on functions. Both unary (++, –, !) and binary (+, -, *, /, ==) operators.
Friend Function Usage Not required. Can use friend functions for non-member overloading.

Operators That Can Be Overloaded in C++

Below is a list of operators that can be overloaded in C++:

Category of Operators Operators
Arithmetic Operators +, -, *, /, %
Relational (Comparison) Operators ==, !=, <, >, <=, >=
Logical Operators &&
Bitwise Operators &
Assignment Operators =, +=, -=, *=, /=, %=, &=, |
Increment and Decrement Operators ++, – –
Subscript Operator []
Function Call Operator ()
Pointer Operators * (dereference), -> (member access)
Stream Insertion and Extraction Operators <<, >>

Operators That Cannot Be Overloaded in C++

Below are some of the operators that cannot be overloaded in C++:

1. [::] (Scope Resolution) – Scope resolution is used to access the namespace and class members, and redefining it will break the basic C++ syntax.

2. [ . ](Member Access) – It directly accesses the object members, and overloading it would interfere with the member access rules.

3. [.* ](Pointer-to-Member) – It is used to access the class members through the pointers, and if you try to change it, then it disrupts the behavior of the pointer.

4. [?:] (Ternary Operator) – The ternary operator is used for the complex evaluation order, and overloading it would change the conditional expressions.

5. sizeof – The sizeof operator in C++ is used to determine the size of the object, which is evaluated at compile time. So, it cannot be changed to work at runtime.

6. typeid – It is used for runtime type identification (RTTI), and thus, overloading it would break the built-in type checking.

Rules and Idioms for Operator Overloading in C++

To make sure that there is clear and maintainable operator overloading in C++, the basic rules and idioms must be followed. These are the operator’s precedence and associativity, or the number of operands, which cannot be changed and can only be overloaded by existing operators. Understanding these C++ operator overloading rules is crucial for anyone learning how to overload operators in C++.

Binary Operator Overloading in C++

Binary Operator Overloading in C++

Binary operator overloading in C++ allows user-defined classes to redefine the behavior of the binary operators when they are used with the objects. Also, a binary operator operates on two operands, which makes it different from a unary operator.

A binary operator in C++ can be overloaded in two ways:

1. It can be overloaded as a member function when the left operand is an object of the class. This is a common approach for binary operator overloading in C++.

Example:

Cpp

Output:

member function Output

The code shows how the binary operator * is overloaded as a member function to perform the matrix multiplication on the Matrix objects, which computes the product of two 2*2 matrices and prints the result to the console.

2. It can be overloaded as a friend function (non-member function) when the left operand is not an object of the class. This provides flexibility for binary operator overloading in C++.

Example:

Cpp

Output:

as a friend function Output

The code shows how the binary operator + is overloaded using a friend function in the C++ program to add two Complex numbers and print the result to the console. This example shows a common way of overloading + operator in C++.

Member vs. Non-member Operator Overloads

Aspect Member Function Non-Member Function
Where it’s written Inside the class Outside the class
Number of inputs One (right-side value) Two (left and right-side values)
Left-side object Must be the class object Can be any type (e.g., int + MyClass)
Access to private data Yes Only if it’s a friend function
Good for When the left side is always a class object When the left side might be something else
Example MyClass::operator+(MyClass b) operator+(MyClass a, MyClass b)
Common Use Simple operations where class is on the left Mixed-type operations or symmetry (a + b = b + a)

Unary Operator Overloading

Overloading Unary Operators in C++

Unary operator overloading in C++ allows the user to change the behavior of a single operand operator for user-defined data types. A unary operator in C++ can be overloaded using the member functions since it works on a single object.

Example:

Cpp

Output:

Unary operator overloading in C++ Output

The code shows how the unary operator (-) is overloaded in C++ to negate the value of a Number object, which returns a new object with the negated value, and then the values are printed to the console.

Advanced Operator Overloading: [], (), ->, new/delete

Below are a few operators that can be overloaded, other than the relational and arithmetic operators:

1. Overloading the [ ] (Subscript Operator)

The subscript operator in C++ is overloaded to provide custom behavior as an array, and it must be implemented as a member function. This is a specialized form or method of C++ operator overloading.

Example:

Cpp

Output:

Overloading the [ ] (Subscript Operator) Output

The code shows how the subscript operator is overloaded to provide the custom behavior as an array to access the elements and changes with the bound checking.

2. Overloading the () (Function Call Operator)

Overloading the function call operator allows objects to be used as a function in a C++ program.

Example:

Cpp

Output:

Overloading the () (Function Call Operator) Output

The code shows how the function call ( ) operator is overloaded to allow the Multiplier object to be used as a function to multiply two numbers, 5 and 4, and then the result is printed to the console.

3. Overloading the -> (Arrow Operator)

The arrow operator in C++ is overloaded to return a pointer to an object for a smart pointer. This is crucial for custom pointer-like behavior in C++ operator overloading.

Example:

Cpp

Output:

Overloading the (Arrow Operator) Output

The code shows how the arrow -> operator is overloaded to allow a SmartPointer object to access the Test class functions, such as the raw pointer.

4. Overloading new and delete Operators

The new and delete operators in C++ are overloaded globally for debugging, logging, and customized memory management.

Example:

Cpp

Output:

Overloading new and delete Operators Output

The code shows how the new and delete operators are overloaded in a C++ program to display custom messages when there is dynamic memory allocation and deallocation.

Advantages of Operator Overloading in C++

  • The operator overloading in C++ improves the code readability by allowing operators to work with user-defined data types. 
  • It provides custom object behavior, which helps in operations such as matrix multiplication and complex number addition.
  • It improves the code reusability as the overloaded operators can be reused in different classes and reduces redundant function calls.
  • Operator overloading in C++ supports user-defined data types and maintains consistency with the built-in types. 
  • It is also important to enable the smart pointers for custom memory management through operator overloading in C++.

Disadvantages of Operator Overloading in C++

  • Overloading multiple C++ operators increases the code complexity because the code becomes harder to read and maintain.
  • The overloaded operators that have function calls give a slight performance overhead.
  • If the overloading is not done properly, then the overloaded operators will behave unexpectedly.
  • All operators cannot be overloaded; thus, it limits the customization of operators.
  • It is very difficult to find the errors in the overloaded operators as they work implicitly in the expressions.

Operator Overloading Use-Cases

Below are some real-world use cases of operator overloading. 

 1. Scientific and Engineering Calculations: In science and engineering, most problems revolve around numbers, equations, and relationships, due to which engineers deal with complex numbers, matrices, and vectors, and these mathematical calculations need to be represented in code. 

2. Game Development and Graphics Programming: Game development is one of the best real-world examples where operator overloading comes into play. Games are built on physics, movement, and visual transformations, which use vectors, coordinates, and matrices. Without operator overloading, developers have to constantly write code every time. 

3. Financial and Banking Applications: When you are developing software that handles money, accuracy and clarity are everything. To make the calculations persistent, the values are usually stored in cents or as integers to avoid floating-point issues. With operator overloading, arithmetic operations on money, such as addition, subtraction, or comparison, become easy.

4. Graphics and Image Processing: Image and graphics software deals with operations, like adding brightness or applying a filter. All these are mathematical operations that are performed via operator overloading.

Key Takeaways & Best Practices for Operator Overloading in C++

Here are some key C++ operator overloading rules and best practices:

  • You can only overload the already existing C++ operators.
  • You cannot change the operator’s precedence and associativity by overloading it. This is a fundamental C++ operator overloading rule.
  • All operators cannot be overloaded.
  • The overloaded operators have at least one operand that must be a user-defined type.
  • Operators can be overloaded as member and non-member functions.
  • Also, you cannot overload the operators for the standard data types such as int, float, etc.
  • The operators = and & are by default overloaded in C++.

Common Pitfalls in Operator Overloading

  1. Failing to overload both operand sequences, such as allowing (MyClass + int) but not (int + MyClass).
  2. Avoiding to mark as const to parameters or functions, which can lead to unexpected changes.
  3. Returning references to local variables can cause undefined behavior and should be avoided.
  4. Giving an operator an unexpected meaning, like taking + and making it subtraction. 
  5. Not handling self-assignment in your assignment operator (operator=).
  6. Forgetting to make non-member functions as friend functions when the function needs access to private members, especially for binary operator overloading in C++.
  7. Overloading one comparison operator (ie, ==) without overloading its related operators (eg,!=). 
  8. Overloading operators in C++ when the overload does not improve readability or make the code more difficult to read.

Conclusion

The operator overloading in C++ helps in enhancing code readability, usability, and maintainability by allowing user-defined data types to behave as built-in data types. Also, it helps to simplify the various operations and must not be used unnecessarily. So, by understanding operator overloading with its advantages and disadvantages, you can easily overload the operators in C++ without any confusion or error. This operator overloading tutorial aims to provide you with a comprehensive understanding of how to overload operators in C++.

FAQs on Operator Overloading in C++

Q1. What is operator overloading in C++?

The operator overloading is redefining the standard operators for the user-defined types.

Q2. Why is operator overloading useful?

It improves code readability and usability by enabling intuitive operations on objects.

Q3. Can all C++ operators be overloaded?

No, the operators such as ::, ., .*, sizeof, typeid, and ?: cannot be overloaded.

Q4. What are the types of overloading in C++?

There are two types of overloading in C++: function overloading and operator overloading.

Q5. What are the key rules for operator overloading?

The rules for operator overloading are that at least one operand must be a user-defined type, and operator precedence cannot be changed.

Q6. What is the difference between operator and function overloading?

Operator overloading redefines how operators work with user-defined types, while function overloading allows multiple functions with the same name but different parameters.

Q7. Does operator overloading affect performance in C++?

Yes, operator overloading can affect performance if not used carefully, but it’s usually negligible when implemented efficiently.

Q8. When should you avoid operator overloading?

You should avoid operator overloading when it makes code less readable or breaks expected operator behavior.

About the Author

Software Developer | Technical Research Analyst Lead | Full Stack & Cloud Systems

Ayaan Alam is a skilled Software Developer and Technical Research Analyst Lead with 2 years of professional experience in Java, Python, and C++. With expertise in full-stack development, system design, and cloud computing, he consistently delivers high-quality, scalable solutions. Known for producing accurate and insightful technical content, Ayaan contributes valuable knowledge to the developer community.

Full Stack Developer Course Banner