Operator Overloading
Operator Overloading
In C++, we can change the way operators work for user-defined types like objects and structures. This is known as operator overloading. For example,
Suppose we have created three objects c1, c2 and result from a class named Complex that represents complex numbers.
Since operator overloading allows us to change how operators work, we can redefine how the + operator works and use it to add the complex numbers of c1 and c2 by writing the following code:
result = c1 + c2;
result = c1.addNumbers(c2);
Note: We cannot use operator overloading for fundamental data types like int, float, char and so on.
class className {
... .. ...
public
returnType operator symbol (arguments) {
... .. ...
}
... .. ...
};
Here,
operator is a keyword.
#include <iostream>
using namespace std;
class Count {
private:
int value;
public:
void display() {
cout << "Count: " << value << endl;
}
};
int main() {
Count count1;
count1.display();
return 0;
}
Run Code
Output
Count: 6
Here, when we use ++count1;, the void operator ++ () is called. This increases the value attribute for the object count1 by 1.
Note: When we overload operators, we can use it to work in any way we like. For example, we could have used ++ to increase value by 100.
However, this makes our code confusing and difficult to understand. It's our job as a programmer to use operator overloading properly and in a consistent and intuitive way.
The above example works only when ++ is used as a prefix. To make ++ work as a postfix we use this syntax.
Notice the int inside the parentheses. It's the syntax used for using unary operators as postfix; it's not a function parameter.
#include <iostream>
using namespace std;
class Count {
private:
int value;
public:
void display() {
cout << "Count: " << value << endl;
}
};
int main() {
Count count1;
count1.display();
return 0;
}
Run Code
Output
Count: 6
Count: 7
The Example 2 works when ++ is used as both prefix and postfix. However, it doesn't work if we try to do something like this:
// Error
result = ++count1;
This is because the return type of our operator function is void. We can solve this problem by making Count as the return type of the operator function.
Count operator ++ () {
// code
}
class Count {
private:
int value;
public
:
// Constructor to initialize count to 5
Count() : value(5) {}
return temp;
}
return temp;
}
void display() {
cout << "Count: " << value << endl;
}
};
int main() {
Count count1, result;
return 0;
}
Run Code
Output
Count: 6
Count: 6
Here, we have used the following code for prefix operator overloading:
return temp;
}
The code for the postfix operator overloading is also similar. Notice that we have created an object temp and returned its value to the operator function.
Also, notice the code
temp.value = ++value;
The variable value belongs to the count1 object in main() because count1 is calling the function, while temp.value belongs to the temp object.
result = num + 9;
The operator function is called using the obj1 object and obj2 is passed as an argument to the function.
#include <iostream>
using namespace std;
class Complex {
private:
float real;
float imag;
public:
// Constructor to initialize real and imag to 0
Complex() : real(0), imag(0) {}
void input() {
cout << "Enter real and imaginary parts respectively: ";
cin >> real;
cin >> imag;
}
void output() {
if (imag < 0)
cout << "Output Complex number: " << real << imag << "i";
else
cout << "Output Complex number: " << real << "+" << imag << "i";
}
};
int main() {
Complex complex1, complex2, result;
return 0;
}
Run Code
Output
However,
using & makes our code efficient by referencing the complex2 object instead of making a duplicate object inside the operator function.
using const is considered a good practice because it prevents the operator function from modifying complex2.
a. :: (scope resolution)
b. . (member selection)
c. .* (member selection through pointer to function)
d. ?: (ternary operator)