C++ Operator Overloading
Customizing operator behavior for user-defined types
⚙️ What is Operator Overloading?
Operator overloading allows you to redefine the behavior of operators for user-defined classes, making objects work with standard operators like +, -, *, etc.
// Simple operator overloading example
class Point {
public:
int x, y;
Point(int x = 0, int y = 0) : x(x), y(y) {}
Point operator+(const Point& other) {
return Point(x + other.x, y + other.y);
}
};
Usage:
Point p1(3, 4);
Point p2(1, 2);
Point p3 = p1 + p2; // (4, 6)
Types of Operator Overloading
Arithmetic
+, -, *, /, % operators
Complex operator+(const Complex& c) {
return Complex(real + c.real, imag + c.imag);
}
Assignment
=, +=, -=, *=, /= operators
Point& operator=(const Point& other) {
x = other.x; y = other.y;
return *this;
}
Comparison
==, !=, <, >, <=, >= operators
bool operator==(const Point& other) {
return x == other.x && y == other.y;
}
Stream
<<, >> operators for I/O
friend ostream& operator<<(ostream& os, const Point& p) {
return os << "(" << p.x << ", " << p.y << ")";
}
🔹 Complete Example: Complex Number Class
A comprehensive Complex Number class in C++ demonstrates operator overloading for intuitive mathematical
operations. By overloading operators like + and *, you enable natural syntax
such as c1 + c2 and c1 * c2 for complex arithmetic. The class typically includes private
real and imaginary members, constructors, and friend functions for output. This encapsulation allows you to perform
calculations like (3 + 4i) * (1 + 2i) = -5 + 10i directly, making the code more readable and closely
mirroring mathematical notation while ensuring proper memory management.
class Complex {
private:
double real, imag;
public:
Complex(double r = 0, double i = 0) : real(r), imag(i) {}
// Arithmetic operators
Complex operator+(const Complex& c) const {
return Complex(real + c.real, imag + c.imag);
}
Complex operator-(const Complex& c) const {
return Complex(real - c.real, imag - c.imag);
}
Complex operator*(const Complex& c) const {
return Complex(real * c.real - imag * c.imag,
real * c.imag + imag * c.real);
}
// Assignment operator
Complex& operator=(const Complex& c) {
real = c.real;
imag = c.imag;
return *this;
}
// Comparison operator
bool operator==(const Complex& c) const {
return (real == c.real) && (imag == c.imag);
}
// Stream insertion operator (friend function)
friend ostream& operator<<(ostream& os, const Complex& c) {
os << c.real;
if (c.imag >= 0) os << " + " << c.imag << "i";
else os << " - " << -c.imag << "i";
return os;
}
// Stream extraction operator (friend function)
friend istream& operator>>(istream& is, Complex& c) {
cout << "Enter real part: ";
is >> c.real;
cout << "Enter imaginary part: ";
is >> c.imag;
return is;
}
};
int main() {
Complex c1(3, 4);
Complex c2(1, 2);
Complex c3 = c1 + c2;
Complex c4 = c1 * c2;
cout << "c1 = " << c1 << endl;
cout << "c2 = " << c2 << endl;
cout << "c1 + c2 = " << c3 << endl;
cout << "c1 * c2 = " << c4 << endl;
return 0;
}
Output:
c1 = 3 + 4i
c2 = 1 + 2i
c1 + c2 = 4 + 6i
c1 * c2 = -5 + 10i
🔹 Unary Operator Overloading
Overloading unary operators like ++, --, and - allows objects to
behave like built-in types. You can define both prefix (e.g., ++obj) and postfix (e.g.,
obj++) versions by using an int dummy parameter for postfix. For instance, a
Counter class might increment or decrement an internal count, returning the appropriate value or
reference. This enables intuitive operations such as Count: 6 becoming Count: 7 after
incrementing, making user-defined types more expressive and integrated with C++'s idiomatic patterns.
class Counter {
private:
int count;
public:
Counter(int c = 0) : count(c) {}
// Pre-increment operator
Counter& operator++() {
++count;
return *this;
}
// Post-increment operator
Counter operator++(int) {
Counter temp = *this;
count++;
return temp;
}
// Unary minus operator
Counter operator-() const {
return Counter(-count);
}
void display() const {
cout << "Count: " << count << endl;
}
};
int main() {
Counter c1(5);
++c1; // Pre-increment
c1.display(); // Count: 6
Counter c2 = c1++; // Post-increment
c1.display(); // Count: 7
c2.display(); // Count: 6
Counter c3 = -c1; // Unary minus
c3.display(); // Count: -7
return 0;
}
Output:
Count: 6
Count: 7
Count: 6
Count: -7