Operator Overloading in C++ (original) (raw)
Last Updated : 17 Jan, 2026
Operator overloading means giving a new meaning to an operator (like +, -, *, []) when it is used with objects.
- With operator overloading, we can make operators work for user defined classes structures.
- It is an example of compile-time polymorphism.
**Example: In this example, the + operator is overloaded to add two Number objects.
C++ `
#include using namespace std;
struct Number { int value;
Number(int v)
{
value = v;
}
// Overload + operator
Number operator+(const Number &n)
{
return Number(value + n.value);
}
void display()
{
cout << value << endl;
}};
int main() { Number n1(5), n2(10); Number n3 = n1 + n2; n3.display(); }
`
Why use Operator Overloading?
- Allows objects to behave like basic data types.
- Useful for mathematical objects like Complex numbers and Vectors.
- Reduces the need for extra function calls.
Operator Functions vs Normal Functions
| Feature | Operator Function | Normal Function |
|---|---|---|
| Syntax | Uses operator keyword | Standard function name |
| Invocation | Triggered by using an operator | Called explicitly by name |
| Purpose | Redefines behavior of operators | Performs defined actions |
| Example | operator+() | add() |
Operators That Cannot Be Overloaded
The following operators cannot be overloaded in C++:
- sizeof
- typeid
- Scope resolution (::)
- Class member access operators (. and .*)
- Ternary / conditional operator (?:)
Why These Operators Cannot Be Overloaded?
1. sizeof Operator
- Evaluated at compile time
- Used internally for memory layout and pointer arithmetic
- Overloading would break fundamental language behavior
2. typeid Operator
- Used for runtime type identification
- Must uniquely identify a type
- Altering its meaning would break RTTI and polymorphism guarantees
3. Scope resolution (::) Operator
- Works on names, not values
- Fully resolved at compile time
- There is no syntax to intercept or overload name resolution
4. Class Member Access Operators (. and .*)
- Implicitly used by the compiler to access members
- Overloading would break object access semantics
The importance and implicit use of class member access operators can be understood through the following example:
C++ `
#include using namespace std;
class Complex { private: int real; int imaginary;
public: Complex(int real, int imaginary) { this->real = real; this->imaginary = imaginary; } void print() { cout << real << " + i" << imaginary; } Complex operator+(Complex c2) { Complex c3(0, 0); c3.real = this->real + c2.real; c3.imaginary = this->imaginary + c2.imaginary; return c3; } }; int main() { Complex c1(3, 5); Complex c2(2, 4); Complex c3 = c1 + c2; c3.print(); return 0; }
`
**Explanation:
- "c1 + c2" is translated internally to "c1.operator+(c2)"
- The dot operator is implicitly required to invoke member functions
- Since this operator is fundamental to object access, it cannot be overloaded
5. Ternary or conditional (?:) Operator
- Evaluates **only one of the two expressions based on a condition
- Function calls cannot enforce short-circuit evaluation
- Overloading would break conditional execution guarantees
Important Points About Operator Overloading
- At least one operand must be a user-defined type
- Operators can be overloaded as member or non-member functions
- Some operators (like conversion operators) must be member functions
Conversion Operator Example:
C++ `
#include using namespace std;
class Fraction { private: int num, den;
public: Fraction(int n, int d) { num = n; den = d; }
// Conversion operator
operator float() const
{
return float(num) / float(den);
}};
int main() { Fraction f(2, 5); float val = f; cout << val << endl; }
`
**Note: Conversion operators must be member functions.
Conversion Constructors
Any constructor that can be called with a single argument acts as a conversion constructor and enables implicit type conversion.
C++ `
#include using namespace std;
class Point { private: int x, y;
public: Point(int i = 0, int j = 0) { x = i; y = j; } void print() { cout << "x = " << x << ", y = " << y << '\n'; } };
int main() { Point t(20, 20); t.print(); t = 30; t.print(); return 0; }
`
Output
x = 20, y = 20 x = 30, y = 0