Difference between Function Overloading and Operator Overloading in C++
Function overloading and operator overloading are two sub-categories under static polymorphism. Static polymorphism is the situation where the function to be executed is determined during compile time.
Before exploring the differences between operator overloading and function overloading, let us see in detail about each.
Function overloading
Function overloading is a type of static polymorphism where the function with the same name but distinct parameter lists is defined in the same scope. When the function is called, the suitable function is determined by the number and types of arguments used in the function call. Function overloading enables multiple function implementations to handle different data types or behaviors.
Let us see the example of function overloading.
Declare the function with the same name but a different parameter list for function overloading.
Example
Int sub (int a, int b);
Int sub (float m, float n);
Let us see a simple program on function overloading
Program
#include <iostream>
class Calculator {
public:
// Function with the same name but different parameter lists
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
};
int main() {
Calculator calc;
int result1 = calc.add(3, 5); // Calls the int add(int a, int b) function
double result2 = calc.add(3.5, 2.7); // Calls the double add(double a, double b) function
std::cout << "Result 1: " << result1 << std::endl;
std::cout << "Result 2: " << result2 << std::endl;
return 0;
}
Output:
Explanation:
The above program demonstrated the function overloading by defining the two functions with the same name but different parameter lists. When we call the function, the appropriate function gets invoked with the help of a matching parameter list.
Operator Overloading
Operator overloading in C++ allows you to redefine or customize the behavior of operators for user-defined data types like classes and structures. It enables you to change how these operators work when applied to objects of your custom types.
Steps to define and use the constructor
1. Define class or structure.
Create a class or structure representing a custom data type, including data members and methods to operate on those members.
2. Select the operator to overload.
Choose which operator or operators you want to overload. Commonly overloaded operators include +, -, *, /, ==, !=, =, [], (), and more. However, it's important to note that certain operators like sizeof, typeid, the scope resolution (::), the class member access operator (.), and the ternary or conditional operator (?:) cannot be overloaded.
3. Define the overload function.
You can define a member or friend function within your class to overload an operator. The function should have the operator symbol as the function name, and the return type and parameters should depend on the overloaded operator.
Using member function
ReturnType operatorSymbol(Parameters) { // Custom behavior for the operator }
Using friend function
friend ReturnType operatorSymbol(Parameters);
4. Implement the Custom Behavior for an operator.
Implement the custom behavior inside the operator overload function using the data members and methods of the class.
5. Use an overloaded operator
You can use the overloaded operator with objects of your class, like built-in types.
Example
Let us consider an example of operator overloading
Unary operator overloading
In C++, you can overload unary operators, which act on a single operand, for user-defined classes or structures. Unary operators commonly used include +, -, ++, --, and !. By overloading unary operators, you can define custom behaviors for these operators when applied to your class's objects.
Example:
Let us see an example on unary operator overloading.
Program:
#include <iostream>
using namespace std;
class Counter {
private:
int countValue;
public:
// Constructor to initialize countValue to 9
Counter() {
countValue = 9;
}
// Overload the & operator when used as prefix
void operator&() {
countValue--;
}
void display() {
cout << "Counter Value: " << countValue << endl;
}
};
int main() {
Counter counter1;
// Call the overloaded & operator function as a prefix
&counter1;
counter1.display();
return 0;
}
Output:
Explanation:
This program initializes the countValue variable to 9 and then uses the overloaded & operator as a prefix on the counter1 object, which decrements the value to 8. Finally, the updated value of the counter is displayed using the display() method.
The code provides an example of how to overload the & operator as a prefix to perform a specific operation, such as decrementing the counter when the operator is used with an object of the Counter class.
Binary operator overloading
Overloading enables you to define custom behaviours for operators that involve two operands when used with objects of user-defined classes or structures. These operators include +, -, *, /, ==, !=, and more.
Example
Let us consider an example of binary operator overloading
Program:
#include <iostream>
using namespace std;
class MyObject {
private:
int value;
public:
MyObject(int val) : value(val) {}
// Overload the == operator
bool operator==(const MyObject& other) const {
return this->value == other.value;
}
};
int main() {
MyObject obj1(5);
MyObject obj2(5);
MyObject obj3(10);
if (obj1 == obj2) {
cout << "obj1 and obj2 are equal." << endl;
} else {
cout << "obj1 and obj2 are not equal." << endl;
}
if (obj1 == obj3) {
cout << "obj1 and obj3 are equal." << endl;
} else {
cout << "obj1 and obj3 are not equal." << endl;
}
return 0;
}
Output:
Explanation:
The program customizes the behavior of the operator to compare MyObject instances based on their value member. This allows you to use the == operator with MyObject objects to check if they are equal, just like you would with built-in types.
Function overloading vs Operator overloading
Basis | Function Overloading | Operator Overloading |
Definition | Function overloading involves defining multiple functions with the same name and distinct parameter list. | Operator overloading involves customizing the operator's behavior when it works with the objects of a user-defined class and structures. |
Purpose | It is used for defining multiple functionalities of a function | It is used to perform operations on objects of class and structures. |
Syntax | ReturnType function1 name(parameter list1) ReturnType function1 name(parameter lsit2) | Return type operator operator symbol (parameter list){custom behavior} |
Compared to normal function | Same as the normal function declaration. | The operator overloading function includes the new keyword "operator" and the operator symbol. |
Example | Void add(int a, int b){}; Void add(float a, float b){}; | Void operator +(){ //custom behavior } |
Conclusion
To summarize, although function and operator overloading enables more flexible and expressive code, they possess distinct purposes and applications. Function overloading is mainly utilized to offer multiple ways of executing operations with different parameter lists, which improves code readability. Conversely, operator overloading enables you to redefine the behaviors of operators for customized data types, creating more intuitive and expressive code, especially in domain-specific contexts. Selecting the appropriate technique will depend on your program or class's specific requirements and design goals.