C++ Learning Manual – Operator Overloading and Friends – Operator Overloading (+, -, <<, >>)

Why Overload Operators?

Imagine you have created a class <span>Complex</span> that represents complex numbers, containing real and imaginary parts. You want to use operations like <span>c1 + c2</span> directly, just like with basic types, instead of calling a function like <span>c1.add(c2)</span>. This is the purpose of operator overloading – to make custom types as convenient to use as built-in types.

1. How to Overload Arithmetic Operators (+, -)

We overload the <span>+</span> and <span>-</span> operators using member functions.

#include <iostream>
using namespace std;

class Complex {
private:
    double real;
    double imag;
public:
    Complex(double r = 0, double i = 0) : real(r), imag(i) {}
    
    // Overload + operator
    Complex operator+(const Complex& other) const {
        return Complex(real + other.real, imag + other.imag);
    }
    
    // Overload - operator  
    Complex operator-(const Complex& other) const {
        return Complex(real - other.real, imag - other.imag);
    }
};

int main() {
    Complex c1(1.0, 2.0);
    Complex c2(3.0, 4.0);
    
    Complex c3 = c1 + c2;  // As simple as 1+2
    Complex c4 = c1 - c2;
    
    return 0;
}

Brief Explanation:

  • <span>operator+</span> is the function name
  • <span>const Complex& other</span> represents the number on the right
  • Returns a new object without modifying the original object

2. How to Overload Input and Output Operators (<<, >>)

Here’s a question:<span>cout << c1</span> has <span>cout</span> on the left and our object on the right. Therefore, we cannot use a member function; we need to use global functions.

However, global functions cannot access private members of the class, so we need to use friends.

class Complex {
private:
    double real;
    double imag;
public:
    Complex(double r = 0, double i = 0) : real(r), imag(i) {}
    
    // Declare friend functions to allow access to private members
    friend ostream& operator<<(ostream& os, const Complex& c);
    friend istream& operator>>(istream& is, Complex& c);
};

// Implement output <<
ostream& operator<<(ostream& os, const Complex& c) {
    os << "(" << c.real << " + " << c.imag << "i)";
    return os;
}

// Implement input >>
istream& operator>>(istream& is, Complex& c) {
    is >> c.real >> c.imag;
    return is;
}

int main() {
    Complex c1;
    cout << "Enter a complex number (real part imaginary part):";
    cin >> c1;          // Use overloaded >>
    cout << c1 << endl; // Use overloaded <<
    
    return 0;
}

Brief Explanation:

  • <span>friend</span> allows global functions to access private members
  • <span>ostream&</span> and <span>istream&</span> represent input and output streams
  • Returning a stream reference supports chaining operations:<span>cout << c1 << c2</span>

Summary

  1. Arithmetic operators (+, -, *, /): overloaded using member functions
  2. Stream operators (<<, >>): overloaded using global functions, requiring <span>friend</span>
  3. The role of friends: allowing external functions to access private members of the class

Operator overloading makes the code more intuitive; for example, <span>c1 + c2</span> looks much more natural than <span>c1.add(c2)</span>. Mastering this technique will make your custom classes as convenient to use as built-in types!

Java Learning Materials Available

C Language Learning Materials Available

Frontend Learning Materials Available

C++ Learning Materials Available

PHP Learning Materials Available

Leave a Comment