0% found this document useful (0 votes)
2 views27 pages

Notes Operator Overloading

Operator overloading allows redefining operator behavior for user-defined types, enhancing code readability and making object-oriented programming cleaner. It follows specific rules, such as only existing operators can be overloaded and some must be member functions. The document includes examples of overloading various operators, including arithmetic, comparison, and I/O stream operators, along with practice questions.

Uploaded by

muhammadzainf15
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views27 pages

Notes Operator Overloading

Operator overloading allows redefining operator behavior for user-defined types, enhancing code readability and making object-oriented programming cleaner. It follows specific rules, such as only existing operators can be overloaded and some must be member functions. The document includes examples of overloading various operators, including arithmetic, comparison, and I/O stream operators, along with practice questions.

Uploaded by

muhammadzainf15
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Notes

Operator Overloading
What is Operator Overloading?

Operator overloading allows us to redefine the behavior of operators (+, -, *, =, etc.) for
user-defined types (classes).

This makes operations on objects more intuitive and readable.

Why Overload Operators?

▪ Allows natural operations on objects (e.g., p1 + p2 instead of [Link](p2)).

▪ Makes object-oriented programming (OOP) cleaner.

▪ Improves code readability and maintainability.


Operator Overloading

Rules for Operator Overloading

▪ Only existing operators can be overloaded.

▪ Precedence and associativity of operators do not change.

▪ Some operators must be member functions (=, (), [], ->).

▪ Other operators can be member functions or global functions.

▪ Cannot overload ::, .*, sizeof, typeid, etc.


Operator Overloading

Syntax for Operator Overloading

Operators can be overloaded:

1. As a member function (operates on this object).

2. As a global function (operates on objects passed as arguments).


Operator Overloading
General Syntax (Member Function)

class ClassName {
public:
ReturnType operator OpSymbol (const ClassName& obj) {
// Define operation
}
};
General Syntax (Global Function)

ReturnType operator OpSymbol (const ClassName& obj1, const ClassName& obj2) {


// Define operation
}
Overloading Operators in a Simple Point Class
class Point {
private: // Overloading - operator (global function)
int x, y; // Global function for – operator

public: Point operator - (const Point& p1, const Point& p2) {


// Constructor return Point([Link]() - [Link](), [Link]() - [Link]());
Point(int a = 0, int b = 0) : x(a), y(b) {} }

// Overloading + operator (member function) int main() {


Point p1(3, 4), p2(1, 2);
Point operator + (const Point& p) const {
return Point(x + p.x, y + p.y); Point p3 = p1 + p2; // Uses member function
} Point p4 = p1 - p2; // Uses global function

void display() const { cout << "p1: "; [Link]();


cout << "(" << x << ", " << y << ")" << endl; cout << "p2: "; [Link]();
} cout << "p1 + p2: "; [Link]();
cout << "p1 - p2: "; [Link]();
// Getter functions for accessing private members
int getX() const { return x; } return 0;
int getY() const { return y; } }
};
Point operator+(const Point& p) const {
return Point(x + p.x, y + p.y);
}
Point operator+(const Point& p) const {
Point temp;
temp.x = x + p.x;
temp.y = y + p.y;
return temp;
}

Point operator+(const Point& p) const {


return Point(this->x + p.x, this->y + p.y);
}

Point operator+(const Point& p) const {


return Point((x > 0 ? x + p.x : x), (y > 0 ? y + p.y : y));
}
Overloading ++ and -- (Pre/Post Increment)

// Pre-increment (++p) // Post-increment (p++)

Point& operator ++ () { Point operator ++ (int) {


x++; y++; Point temp = *this;
return *this; x++; y++;
} return temp;
}
Overloading == (Equality Comparison)

bool operator == (const Point& p) const {


return (x == p.x && y == p.y);
}
Overloading << and >> (I/O Stream Operators)

ostream& operator<<(ostream& out, const Point& p) {


out << "(" << [Link]() << ", " << [Link]() << ")";
return out;
}

istream& operator>>(istream& in, Point& p) {


int a, b;
in >> a >> b;
p = Point(a, b);
return in;
}
Practice Questions

1. Overload the * operator for scalar multiplication (p * 2).

2. Overload the / operator for division by a scalar.

3. Implement a Complex class with overloaded +, -, and * operators.

4. Overload the [] operator for accessing Point coordinates (p[0] for x, p[1] for y).

5. Overload == and != to compare two Point objects.


Operator Purpose

+ Adds two objects (p1 + p2)


- Subtracts two objects (p1 - p2)
* Multiplies object with scalar (p1 * 2)
/ Divides object by scalar (p1 / 2)
[] Accesses elements (p[0], p[1])
== Checks equality (p1 == p2)
!= Checks inequality (p1 != p2)
1. Overloading * Operator for Scalar Multiplication (p * 2)

class Point {
private:
int x, y; int main() {
Point p1(3, 4);
public: Point p2 = p1 * 2; // Multiply point by 2
Point(int a = 0, int b = 0) : x(a), y(b) {}
cout << "p1: "; [Link]();
// Overloading * operator for scalar multiplication cout << "p1 * 2: "; [Link]();
Point operator*(int scalar) const {
return Point(x * scalar, y * scalar); return 0;
} }

void display() const {


cout << "(" << x << ", " << y << ")" << endl;
}
};
p1: (3, 4)
p1 * 2: (6, 8)
2. Overloading / Operator for Division by a Scalar (p / 2)

class Point {
private:
int x, y;
int main() {
public:
Point p1(10, 20);
Point(int a = 0, int b = 0) : x(a), y(b) {}
Point p2 = p1 / 2; // Divide point by 2
// Overloading / operator for scalar division
cout << "p1: "; [Link]();
Point operator/(int scalar) const {
cout << "p1 / 2: "; [Link]();
if (scalar == 0) {
cout << "Error: Division by zero!" << endl;
return 0;
return *this;
}
}
return Point(x / scalar, y / scalar);
}

void display() const {


cout << "(" << x << ", " << y << ")" << endl;
} p1: (10, 20)
}; p1 / 2: (5, 10)
3. Implementing a Complex Class with Overloaded +, -, and * Operators
class Complex {
private:
double real, imag;

public: int main() {


Complex(double r = 0, double i = 0) : real(r), imag(i) {}
Complex c1(3, 4), c2(1, 2);
// Overloading + operator
Complex operator+(const Complex& c) const { Complex sum = c1 + c2;
return Complex(real + [Link], imag + [Link]); Complex diff = c1 - c2;
} Complex prod = c1 * c2;

// Overloading - operator cout << "c1: "; [Link]();


Complex operator-(const Complex& c) const { cout << "c2: "; [Link]();
return Complex(real - [Link], imag - [Link]);
cout << "c1 + c2: "; [Link]();
}
cout << "c1 - c2: "; [Link]();
// Overloading * operator cout << "c1 * c2: "; [Link]();
Complex operator*(const Complex& c) const {
return Complex(real * [Link] - imag * [Link], real * [Link] + imag * [Link]); return 0;
} } c1: 3 + 4i
void display() const { c2: 1 + 2i
cout << real << " + " << imag << "i" << endl; c1 + c2: 4 + 6i
} c1 - c2: 2 + 2i
}; c1 * c2: -5 + 10i
4. Overloading [] Operator for Accessing Point Coordinates (p[0] for x, p[1] for y)

class Point {
private:
int x, y;

public: int main() {


Point(int a = 0, int b = 0) : x(a), y(b) {} Point p1(5, 10);
cout << "p1[0]: " << p1[0] << endl;
// Overloading [] operator cout << "p1[1]: " << p1[1] << endl;
int operator[](int index) const { cout << "p1[2]: " << p1[2] << endl; // Invalid index
if (index == 0) return x;
if (index == 1) return y; return 0;
cout << "Error: Invalid index!" << endl; }
return -1;
}

void display() const {


cout << "(" << x << ", " << y << ")" << endl;
} p1[0]: 5
}; p1[1]: 10
Error: Invalid index!
p1[2]: -1
5. Overloading == and != to Compare Two Point Objects
class Point {
private:
int x, y;

public:
Point(int a = 0, int b = 0) : x(a), y(b) {}
int main() {
// Overloading == operator
Point p1(3, 4), p2(3, 4), p3(5, 6);
bool operator==(const Point& p) const {
return (x == p.x && y == p.y);
cout << "p1 == p2: " << (p1 == p2) << endl; // True (1)
}
cout << "p1 == p3: " << (p1 == p3) << endl; // False (0)
cout << "p1 != p3: " << (p1 != p3) << endl; // True (1)
// Overloading != operator
bool operator!=(const Point& p) const {
return 0;
return !(*this == p); // Uses the overloaded ==
}
}

void display() const {


cout << "(" << x << ", " << y << ")" << endl; p1 == p2: 1
} p1 == p3: 0
}; p1 != p3: 1
1. Operators That Can Be Overloaded

Operator Description
Operator Description
+= Addition assignment
+ Addition
-= Subtraction assignment
- Subtraction
*= Multiplication assignment
* Multiplication
/= Division assignment
/ Division
%= Modulus assignment
% Modulus
<< Output stream (cout <<)
++ Increment (pre/post)
>> Input stream (cin >>)
-- Decrement (pre/post)
& Address-of (not recommended to overload)
== Equality check
^ Bitwise XOR
!= Inequality check
&= Bitwise AND assignment
> Greater than
^= Bitwise XOR assignment
< Less than
~ Bitwise NOT
>= Greater than or equal to
&& Logical AND
<= Less than or equal to
! Logical NOT
= Assignment
, Comma operator
-> Member access (rarely overloaded)
->* Pointer to member
() Function call operator
[] Subscript operator
2. Operators That Cannot Be Overloaded

Operator Description

. Member access ([Link])

.* Pointer-to-member selection

:: Scope resolution (ClassName::member)

sizeof Size operator (sizeof(type))

typeid Runtime type identification

alignof Alignment requirement

new and delete Memory allocation/deallocation (can be overloaded globally but not per class)
class Point {
private:
double x;
double y;
public:
Point(double xVal = 0.0 , double yVal = 0.0) : x(xVal), y(yVal) {}
// Getter for x
double getX() const {
return x;
}
// Setter for x
void setX(double newX) {
x = newX;
}
// Getter for y
double getY() const {
return y;
}
// Setter for y
void setY(double newY) {
y = newY;
}
// Display
void display() {
cout << "Point(" << x << ", " << y << ")" <<endl;
}
};
// Overload + operator for Point + Point int main() {
Point operator+(const Point& p1, const Point& p2) { Point P1(2.0, 3.0);
Point p; Point P2(1.0, 4.0);
[Link]([Link]() + [Link]());
[Link]([Link]() + [Link]()); // P1 + P2
return p; Point result1 = P1 + P2;
} cout << "P1 + P2 = ";
[Link]();
// Overload + operator for Point + scalar
Point operator+(const Point& p, const double scalar) { // P1 + 5.0
Point r; Point result2 = P1 + 5.0;
[Link]([Link]() + scalar); cout << "P1 + 5.0 = ";
[Link]([Link]() + scalar); [Link]();
return r;
} // 5.0 + P1
Point result3 = 5.0 + P1;
// Overload + operator for scalar + Point cout << "5.0 + P1 = ";
Point operator+(const double scalar, const Point& p) { [Link]();
Point r;
[Link](scalar + [Link]()); return 0;
[Link](scalar + [Link]()); }
return r;
}
// Overload + operator for Point + Point int main() {
Point operator+(const Point& p2) { Point P1(2.0, 3.0);
Point p; Point P2(1.0, 4.0);
p.x = (this->x + p2.x);
p.y = (this->y + p2.y); // P1 + P2
return p; Point result1 = P1 + P2;
} cout << "P1 + P2 = ";
[Link]();
// Overload + operator for Point + scalar
Point operator+(const double scalar) { // P1 + 5.0
Point r; Point result2 = P1 + 5.0;
r.x = (this->x + scalar); cout << "P1 + 5.0 = ";
r.y = (this->x + scalar); [Link]();
return r;
} // 5.0 + P1
}; Point result3 = 5.0 + P1;
cout << "5.0 + P1 = ";
// Overload + operator for scalar + Point [Link]();
Point operator+(const double scalar, const Point& p) {
Point r; return 0;
[Link](scalar + [Link]()); }
[Link](scalar + [Link]());
return r;
}
// Overload pre-increment operator (++Point) int main() {
Point& operator++() { Point P1(2.0, 3.0);
x++; cout << "Original Point: ";
[Link]();
y++;
return *this; // Pre-increment operator (++Point)
} ++P1;
// Overload post-increment operator (Point++) cout << "After Pre-increment: ";
Point operator++(int) { [Link]();
Point temp(*this);
x++; // Post-increment operator (Point++)
Point result1 = P1++;
y++; cout << "After Post-increment: ";
return temp; [Link]();
} cout << "Result of Post-increment: ";
// Overload pre-decrement operator (--Point) [Link]();
Point& operator--() {
x--; // Pre-decrement operator (--Point)
y--; --P1;
cout << "After Pre-decrement: ";
return *this; [Link]();
}
// Overload post-decrement operator (Point--) // Post-decrement operator (Point--)
Point operator--(int) { Point result2 = P1--;
Point temp(*this); cout << "After Post-decrement: ";
x--; [Link]();
y--; cout << "Result of Post-decrement: ";
[Link]();
return temp;
} return 0;
}; }
// Overload unary + operator to return the point itself int main() {
Point operator+() const { Point P1(2.0, 3.0);
return *this;
// Display the original point
}
cout << "Original Point: ";
[Link]();
// Overload unary - operator to negate the point
Point operator-() const { // Use unary + operator
x = -x; Point result1 = +P1;
y = -y; cout << "Unary + Result: ";
return *this; [Link]();
}
// Use unary - operator
Point result2 = -P1;
// Overload unary ! operator to reverse the point's sign cout << "Unary - Result: ";
Point operator!() const { [Link]();
x = !x;
y = !y; // Use unary ! operator
return *this; Point result3 = !P1;
} cout << "Unary ! Result: ";
}; [Link]();

return 0;
}
int main() {
Point P1(2.0, 3.0);
Point P2(2.0, 3.0);
Point P3(4.0, 5.0);
// Overload == operator to compare two Point objects for equality
if (P1 == P2)
{
bool operator==(const Point& other) const {
cout<<"P1 and P2 are equal"<<endl;
bool areEqual = (x == other.x) && (y == other.y); }
return areEqual; else
} {
cout<<"P1 and P2 are not equal"<<endl;
// Overload != operator to compare two Point objects for inequality }

bool operator!=(const Point& other) const { if (P1 != P3)


{
bool areNotEqual = !(*this == other);
cout<<"P1 and P3 are not equal"<<endl;
return areNotEqual; }
} else
}; {
cout<<"P1 and P3 are equal"<<endl;
}
return 0;
}
// Overload << operator for easy printing of Point objects int main() {
friend ostream& operator<<(ostream& os, const Point& point) { Point P1(2.0, 3.0);
os << "Point(" << point.x << ", " << point.y << ")"; Point P2(0.0, 0.0);
return os;
} // Output P1
cout << "P1: " << P1 <<endl;
// Overload >> operator to read Point objects from the input stream
friend istream& operator>>(istream& is, Point& point) { // Input P2 from the user
is >> point.x >> point.y; cout << "Enter coordinates for P2 (x y): ";
return is; cin >> P2;
}
// Output P2
// Overload the copy assignment operator (=) for Point objects cout << "P2: " << P2 <<endl;
Point& operator=(const Point& other) {
if (this != &other) { // Assign P1 to P2 using the copy assignment operator
x = other.x; P2 = P1;
y = other.y;
} // Output P2 (now contains the same values as P1)
return *this; cout << "P2: " << P2 << endl;
} return 0;
}; }
In the context of the Point class, we've covered many of the commonly overloaded operators, including:

Arithmetic operators (+, -, *, /) for addition, subtraction, multiplication, and division.


Comparison operators (== and !=) for equality and inequality.
Output stream operator (<<) for printing Point objects.
Input stream operator (>>) for reading Point objects from the input.
Copy assignment operator (=) for copying one Point object to another.
Unary operators (+, -, !, ++, --) for various operations.

Extra, try yourself as home tasks:


+= and -= operators: You can overload these operators to perform addition and subtraction assignment.

*, /, %, etc., for more advanced arithmetic operations: Depending on your use case, you might need to provide
custom behaviors for these operators.

Relational operators (<, >, <=, >=): If you need custom behavior when comparing Point objects, you can overload
these operators.

[] operator: If your class represents a container or has array-like behavior, you can overload the subscript operator for
element access.

() operator: If your class is callable like a function, you can overload the function call operator.

You might also like