Operator Overloading and Custom Data Types in C++

What You’ll Learn

By the end of this post, you will:

  • Understand how to define custom data types using class
  • Learn what operator overloading is and why it’s useful
  • Overload operators like +, ==, and << for your own types
  • Build intuitive and readable class-based code

Why Create Custom Data Types?

C++ lets you define your own types using class or struct, which group data and functions together.

This allows you to model real-world entities more naturally.

Example:

To model a complex number:

class Complex {
public:
double real;
double imag;
};

You now have a new data type: Complex.


What is Operator Overloading?

Operator overloading allows you to redefine how operators work for your custom types.

Example:

  • Instead of writing add(c1, c2);
  • You can simply write c1 + c2; if you overload the + operator

This makes code cleaner and more intuitive.


Defining a Class with Operator Overloading

Let’s walk through creating a simple Complex number class and overload some basic operators.


Step 1: Define the Class

class Complex {
public:
double real, imag;

// Constructor
Complex(double r = 0, double i = 0) {
real = r;
imag = i;
}

// Display function
void display() {
cout << real << " + " << imag << "i" << endl;
}
};

Step 2: Overload the + Operator

We want to allow c1 + c2 where both are Complex objects.

Complex operator+(const Complex& c) {
return Complex(real + c.real, imag + c.imag);
}

Add this method inside the Complex class.

Complete Class with + Overloaded:

class Complex {
public:
double real, imag;

Complex(double r = 0, double i = 0) {
real = r;
imag = i;
}

Complex operator+(const Complex& c) {
return Complex(real + c.real, imag + c.imag);
}

void display() {
cout << real << " + " << imag << "i" << endl;
}
};

Usage:

Complex c1(3.5, 2.5);
Complex c2(1.5, 4.5);
Complex result = c1 + c2;
result.display(); // Output: 5 + 7i

Overloading the == Operator

You can define what it means for two objects to be “equal”.

bool operator==(const Complex& c) {
return real == c.real && imag == c.imag;
}

Usage:

if (c1 == c2) {
cout << "Equal\n";
} else {
cout << "Not Equal\n";
}

Overloading the << Operator (for cout)

To use cout << object, you must define operator<< as a friend function.

friend ostream& operator<<(ostream& out, const Complex& c) {
out << c.real << " + " << c.imag << "i";
return out;
}

Updated Class:

class Complex {
public:
double real, imag;

Complex(double r = 0, double i = 0) : real(r), imag(i) {}

Complex operator+(const Complex& c) {
return Complex(real + c.real, imag + c.imag);
}

bool operator==(const Complex& c) {
return real == c.real && imag == c.imag;
}

friend ostream& operator<<(ostream& out, const Complex& c) {
out << c.real << " + " << c.imag << "i";
return out;
}
};

Usage:

Complex c1(2, 3), c2(2, 3);
cout << c1 << endl;

if (c1 == c2) {
cout << "Equal\n";
}

Custom Data Types: Another Example — Fractions

You can define a class for fractions and overload operators like +, *, or ==.

class Fraction {
public:
int num, denom;

Fraction(int n = 0, int d = 1) {
num = n;
denom = d;
}

Fraction operator+(const Fraction& f) {
int n = num * f.denom + f.num * denom;
int d = denom * f.denom;
return Fraction(n, d);
}

friend ostream& operator<<(ostream& out, const Fraction& f) {
out << f.num << "/" << f.denom;
return out;
}
};

When Should You Overload Operators?

Use operator overloading when:

  • You’re building a custom data type
  • You want your objects to behave like built-in types
  • It makes the code more readable and natural

Don’t overload if it makes code confusing or less clear.


Quiz: Operator Overloading

Question 1/7

Mini Exercises

  1. Create a Point class with x and y coordinates. Overload + to add two points.
  2. Create a Distance class in meters. Overload == and < to compare distances.
  3. Write a Fraction class and overload * and / operators.
  4. Add a friend ostream& operator<< to any class you’ve made to print it with cout.

Common Mistakes to Avoid

  • Forgetting to return a value from overloaded operators
  • Using non-const references for operator parameters when not needed
  • Not defining friend functions outside the class
  • Overcomplicating logic for simple data types

Summary

In this post, you learned:

  • How to define your own custom data types using class
  • How to overload operators like +, ==, and <<
  • Why operator overloading makes your code cleaner and more readable
  • How to apply these techniques to complex numbers, points, and fractions

What’s Next?

In the next post, we’ll move into revision and final practice — including exercises, mini-projects, and a review of all the concepts you’ve learned.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top