Paper Code: CIC-211
Subject: Object-Oriented Programming Using C++
Unit02, Lecture 07:
Topics Covered: Operator Overloading in C++
Operator Overloading in C++
1. What is Operator Overloading?
2. Syntax and Rules of Operator Overloading
3. Types of Operators that Can Be Overloaded
4. Operators That Cannot Be Overloaded
5. Overloading Unary Operators
6. Overloading Binary Operators
7. Overloading Assignment Operator
8. Overloading Relational Operators
9. Overloading Stream Insertion (<<) and Extraction (>>) Operators
10. Member vs Non-member Functions in Operator Overloading
1. What is Operator Overloading?
Operator overloading is a feature in C++ that-
Allows developers to redefine the behavior of existing operators (like +, -, *, =, etc.) for
user-defined types (classes or structs).
This allows for more intuitive and readable code when working with complex objects, by
using operators in ways similar to their usage with built-in types.
Means, by overloading operators, you can make them work with your custom objects just
like they do with built-in types (e.g., int, float, etc.).
Why Operator Overloading?
In C++, operators like +, -, *, = already work with built-in data types, but when you define your
own classes, these operators won't work unless you define their behavior. For example, if you have
a Complex number class, you can't directly add two Complex objects with + unless you overload
the + operator.
2. Syntax and Rules of Operator Overloading
The syntax for overloading an operator in C++ is:
return_type operator symbol (arguments) {
// code to define the operation
}
Example: 1 +(operator) Overload, Adding two Complex Number
#include <iostream>
using namespace std;
// Define a class for complex numbers
class Complex {
private:
float real;
float imag;
public:
// Constructor
Complex(float r = 0, float i = 0) : real(r), imag(i) {}
// Overload the + operator
Complex operator + (const Complex& obj) {
Complex temp;
[Link] = this->real + [Link];
[Link] = this->imag + [Link];
return temp;
}
// Function to display the complex number
void display() const {
cout << real << " + " << imag << "i" << endl;
}
};
int main() {
// Create two Complex objects
Complex c1(3.5, 2.5);
Complex c2(1.5, 4.5);
// Add them using the overloaded + operator
Complex c3 = c1 + c2;
// Display the result
[Link](); // Output: 5.0 + 7.0i
return 0;
}
3. Types of Operators that Can Be Overloaded
Category Operators
Arithmetic Operators +, -, *, /, %
Relational (Comparison) Operators ==, !=, <, >, <=, >=
Logical Operators &&, `, !`
Bitwise Operators &, `, ^, ~, <<, >>`
Assignment Operators =
+=, -=, *=, /=, %=, &=, `=, ^=, <<=,
Compound Assignment Operators
>>=`
Unary Operators +, -, *, &, ++, --
Subscript Operator []
Function Call Operator ()
Dereference Operator *
Address-of Operator &
Member Access Operators ->, ->*
Allocation/Deallocation Operators new, new[], delete, delete[]
Comma Operator ,
Type Conversion Operators explicit operator Type()
4. Operators That Cannot Be Overloaded
Operators Reason
:: (Scope Resolution) Used to access namespaces, static members, etc.
. (Member Access) Used to directly access members of a class.
.* (Pointer-to-Member) Used with member pointers (overload ->* instead).
?: (Ternary Conditional) Used for conditional expressions (condition ? expr1 : expr2).
5. Overloading Unary Operators
a. Method I
#include <iostream>
using namespace std;
class Number {
private:
int value;
public:
// Constructor
Number(int v = 0) : value(v) {}
// Unary minus implementation in the form of binary-like function
Number operator-(const Number& obj) {
return Number(-[Link]); // Negates the value of the passed object
// Function to display the value
void display() const {
cout << "Value: " << value << endl;
};
int main() {
Number n1(10);
// Calling operator- as a unary minus by passing the object itself
Number n2 = [Link]-(n1); // Pass n1 to the function
cout << "Unary negation using binary-like form: ";
[Link]();
return 0;
b. Method II
#include <iostream>
using namespace std;
class Counter {
private:
int count; // Data member to hold the count value
public:
// Constructor
Counter() : count(0) {}
// Overload Prefix ++ Operator (e.g., ++obj)
Counter& operator++() {
++count; // Increment the count
return *this; // Return the current object (this is for chaining purposes)
}
// Overload Postfix ++ Operator (e.g., obj++)
Counter operator++(int) {
Counter temp = *this; // Save the current state of the object
count++; // Increment the count
return temp; // Return the saved state (before increment)
}
// Method to display the current count value
void display() {
cout << "Count: " << count << endl;
}
};
int main() {
Counter c;
cout << "Initial count:" << endl;
[Link](); // Display initial count
// Prefix Increment (++c)
++c;
cout << "After Prefix Increment (++c):" << endl;
[Link]();
// Postfix Increment (c++)
c++;
cout << "After Postfix Increment (c++):" << endl;
[Link]();
return 0;
}
6. Overloading Binary Operators
Please refer to section 2 above, overloading of binary operator +
7. Overloading Assignment Operator
Method 1: copy constructor
// Online C++ compiler to run C++ program online
#include <iostream>
using namespace std;
class MyClass {
private:
int value; // Simple integer attribute
public:
// Constructor
MyClass(int v = 0) : value(v) {}
// Copy constructor
MyClass(const MyClass& other_obj) {
value = other_obj.value; // Copy the value from the other object
}
// Function to display the value
void display() const {
cout << "Value: " << value << endl;
};
int main() {
MyClass obj1(10); // Create an obj1 with value 10
MyClass obj2; // Create an obj2 with value 0
obj2 = obj1; // Use the copy constructor to create obj2 as a copy of obj1
// Display the values after copy construction
cout << "After copy construction:" << endl;
[Link](); // Output: Value: 10
[Link](); // Output: Value: 10
return 0;
Method 2: using = overload
#include <iostream>
using namespace std;
class MyClass {
private:
int value; // Simple integer attribute
public:
// Constructor
MyClass(int v = 0) : value(v) {}
// Overloading the assignment operator
MyClass& operator=(const MyClass& other_obj) {
// Step 1: Self-assignment check
if (this != &other_obj) {
// Step 2: Copy value from the source object
value = other_obj.value;
}
// Step 3: Return *this to allow chaining
return *this;
}
// Function to display the value
void display() const {
cout << "Value: " << value << endl;
};
int main() {
MyClass obj1(10); // Create an object with value 10
MyClass obj2; // Create another object with default value 0
// Display initial values
cout << "Initial values:" << endl;
[Link](); // Output: Value: 10
[Link](); // Output: Value: 0
// Use overloaded assignment operator
obj2 = obj1;
// Display values after assignment
cout << "After assignment:" << endl;
[Link](); // Output: Value: 10
[Link](); // Output: Value: 10
return 0;
8. Overloading Relational Operators
#include <iostream>
#include <cmath> // For sqrt() function
class Point {
private:
int x, y;
public:
// Constructor to initialize point
Point(int x_val = 0, int y_val = 0) : x(x_val), y(y_val) {}
// Overload the == operator (as a member function)
bool operator==(const Point& other) const {
return (x == other.x && y == other.y);
}
// Overload the < operator (as a member function)
bool operator<(const Point& other) const {
return (sqrt(x*x + y*y) < sqrt(other.x*other.x + other.y*other.y));
}
// Display function to print point coordinates
void display() const {
std::cout << "(" << x << ", " << y << ")";
}
};
int main() {
Point p1(3, 4); // Point with coordinates (3, 4)
Point p2(6, 8); // Point with coordinates (6, 8)
Point p3(3, 4); // Another point with coordinates (3, 4)
std::cout << "Comparing two points p1 and p2:" << std::endl;
// Overloaded == operator
if (p1 == p2) {
std::cout << "p1 is equal to p2" << std::endl;
} else {
std::cout << "p1 is not equal to p2" << std::endl;
}
// Overloaded < operator
if (p1 < p2) {
std::cout << "p1 is closer to the origin than p2" << std::endl;
} else {
std::cout << "p1 is farther from the origin than or equal to p2" << std::endl;
}
std::cout << "\nComparing two points p1 and p3:" << std::endl;
// Overloaded == operator
if (p1 == p3) {
std::cout << "p1 is equal to p3" << std::endl;
} else {
std::cout << "p1 is not equal to p3" << std::endl;
}
return 0;
}
Using Friend Function:
#include <iostream>
#include <cmath> // For sqrt() function
class Point {
private:
int x, y;
public:
// Constructor to initialize point
Point(int x_val = 0, int y_val = 0) : x(x_val), y(y_val) {}
// Friend function to overload the == operator
friend bool operator==(const Point& p1, const Point& p2);
// Friend function to overload the < operator
friend bool operator<(const Point& p1, const Point& p2);
// Display function to print point coordinates
void display() const {
std::cout << "(" << x << ", " << y << ")";
}
};
// Overloading the == operator as a friend function
bool operator==(const Point& p1, const Point& p2) {
return (p1.x == p2.x && p1.y == p2.y);
}
// Overloading the < operator as a friend function (comparison by distance from
origin)
bool operator<(const Point& p1, const Point& p2) {
double distance1 = sqrt(p1.x * p1.x + p1.y * p1.y); // Distance of p1 from origin
double distance2 = sqrt(p2.x * p2.x + p2.y * p2.y); // Distance of p2 from origin
return distance1 < distance2;
}
int main() {
Point p1(3, 4); // Point with coordinates (3, 4)
Point p2(6, 8); // Point with coordinates (6, 8)
Point p3(3, 4); // Another point with coordinates (3, 4)
std::cout << "Comparing two points p1 and p2:" << std::endl;
// Overloaded == operator
if (p1 == p2) {
std::cout << "p1 is equal to p2" << std::endl;
} else {
std::cout << "p1 is not equal to p2" << std::endl;
}
// Overloaded < operator
if (p1 < p2) {
std::cout << "p1 is closer to the origin than p2" << std::endl;
} else {
std::cout << "p1 is farther from the origin than or equal to p2" << std::endl;
}
std::cout << "\nComparing two points p1 and p3:" << std::endl;
// Overloaded == operator
if (p1 == p3) {
std::cout << "p1 is equal to p3" << std::endl;
} else {
std::cout << "p1 is not equal to p3" << std::endl;
}
return 0;
}
9. Overloading Stream Insertion (<<) and Extraction (>>) Operators
- Make an example by your self (to do)
10. Member vs Non-member Functions in Operator Overloading
A. Member function:
The operator function is defined as a member of the class. It implicitly takes the left-hand
operand as the calling object (this pointer).
Only the right-hand operand needs to be passed as an argument.
B. Non-member function:
The operator function is defined outside the class, typically as a friend function to allow
access to private members.
Both left and right operands must be passed as arguments.
Example program to demonstrate both:
#include <iostream>
using namespace std;
class Complex {
private:
int real;
int imag;
public:
// Constructor
Complex(int r = 0, int i = 0) : real(r), imag(i) {}
// Member function to overload + (for adding complex numbers)
Complex operator+(const Complex& obj) {
Complex temp;
[Link] = real + [Link];
[Link] = imag + [Link];
return temp;
// Friend function to overload * (for multiplying complex numbers)
friend Complex operator*(const Complex& obj1, const Complex& obj2);
// Function to display the complex number
void display() {
cout << real << " + " << imag << "i" << endl;
};
// Non-member function to overload * (for multiplying complex numbers)
Complex operator*(const Complex& obj1, const Complex& obj2) {
Complex temp;
[Link] = ([Link] * [Link]) - ([Link] * [Link]);
[Link] = ([Link] * [Link]) + ([Link] * [Link]);
return temp;
int main() {
Complex c1(3, 2), c2(1, 7);
// Using the member function to add complex numbers
Complex c3 = c1 + c2;
cout << "Sum: ";
[Link]();
// Using the non-member (friend) function to multiply complex numbers
Complex c4 = c1 * c2;
cout << "Product: ";
[Link]();
return 0;
References:-
Online
1. Tutorialspoint OOP Tutorial: Comprehensive tutorials on OOP concepts with examples. Link
2. GeeksforGeeks OOP Concepts: Articles and examples on OOP principles and applications. Link
3. [Link]
Book
1. "Object-Oriented Analysis and Design with Applications" by Grady Booch: Classic book covering
fundamental OOP concepts and real-world examples.
2. "Object-Oriented Programming in C++" by Robert Lafore: Detailed guide to OOP in C++, explaining
concepts with a practical example