Mastering C++ Operator Overloading: A Practical Tutorial
In C++, Operator Overloading is a compile-time polymorphism feature that allows you to grant custom meanings to existing C++ operators (like +, -, *, ==, etc.) when they are applied to user-defined data types (objects).
It does not let you create new operators (you cannot invent a ** operator), nor does it change the precedence or associativity of existing ones. It simply makes your custom objects behave intuitively, like built-in data types.
1. Syntax of Operator Overloading
To overload an operator, you define a special member function using the operator keyword followed by the symbol you want to overload.
ReturnType operator Symbol (Arguments) {
// Custom logic here
}2. Overloading Unary Operators
A unary operator operates on a single operand. Examples include the unary minus (-), increment (++), and decrement (--) operators.
When you overload a unary operator as a member function, it takes no arguments because it implicitly operates directly on the object that called it.
Example: Overloading the Unary Minus (-)
Let's change the sign of coordinates in a Space object.
#include <iostream>
using namespace std;
class Space {
private:
int x, y, z;
public:
Space(int a, int b, int c) : x(a), y(b), z(c) {}
// Overloading the unary minus operator
void operator-() {
x = -x;
y = -y;
z = -z;
}
void display() {
cout << "X: " << x << ", Y: " << y << ", Z: " << z << endl;
}
};
int main() {
Space s(10, -20, 30);
cout << "Original: ";
s.display();
-s; // Activates custom operator-() function
cout << "After Unary Minus: ";
s.display();
return 0;
}3. Overloading Binary Operators
A binary operator operates on two operands (like +, -, ==, <, etc.).
When overloaded as a member function, the operator function accepts exactly one argument:
- The object on the left side of the operator invokes the function.
- The object on the right side of the operator is passed into the function as the argument.
Example: Overloading the Binary Plus (+)
Let's overload + to add two mathematical Complex numbers (a + bi).
#include <iostream>
using namespace std;
class Complex {
private:
float real;
float imag;
public:
Complex(float r = 0, float i = 0) : real(r), imag(i) {}
// Overloading binary '+'
// 'other' represents the object on the right side of the '+'
Complex operator+(const Complex &other) {
Complex temp;
temp.real = this->real + other.real;
temp.imag = this->imag + other.imag;
return temp;
}
void display() {
cout << real << " + " << imag << "i" << endl;
}
};
int main() {
Complex c1(3.5, 2.5), c2(1.2, 4.3);
Complex c3;
c3 = c1 + c2; // Equivalent to: c3 = c1.operator+(c2);
cout << "Result: ";
c3.display();
return 0;
}4. Manipulation of Strings Using Operators
While standard library strings (std::string) already have overloaded operators, creating a custom MyString class demonstrates how operators like + (concatenation) and == (comparison) are implemented under the hood.
Example: Custom String Concatenation and Comparison
The code below overloads + to combine text and == to check if two custom strings are identical.
#include <iostream>
#include <cstring>
using namespace std;
class MyString {
private:
char str[100];
public:
MyString(const char s[] = "") {
strcpy(str, s);
}
// Overloading '+' for string concatenation
MyString operator+(const MyString &other) {
MyString temp;
strcpy(temp.str, this->str);
strcat(temp.str, other.str); // Combine both arrays
return temp;
}
// Overloading '==' for string comparison
bool operator==(const MyString &other) {
return (strcmp(this->str, other.str) == 0);
}
void display() {
cout << str << endl;
}
};
int main() {
MyString s1("Hello, ");
MyString s2("World!");
MyString s3;
// Concatenation using +
s3 = s1 + s2;
cout << "Concatenated String: ";
s3.display();
// Comparison using ==
MyString s4("Hello, World!");
if (s3 == s4) {
cout << "Strings match perfectly!" << endl;
} else {
cout << "Strings are different." << endl;
}
return 0;
}Key Constraints of Operator Overloading
While highly versatile, you must keep these rules in mind:
- Non-overloadable operators: The scope resolution operator (::), dot operator (.), pointer-to-member operator (.*), and ternary conditional operator (?:) cannot be overloaded.
- No default arguments: You cannot specify default values for parameters in an operator function.
- Maintain logical consistency: While you can technically make the + operator subtract numbers, doing so creates highly confusing code. Always respect the original intent of the symbol.
English with a size of 5.41 KB