Skip to content

Intermediate · Operator overloading, inheritance and polymorphism · topic 17 of 42 · 30 min

Operator overloading

Explanation

Operator overloading lets your own types use operators such as +, ==, < and <<, so a Money or Fraction type reads like built-in numbers. You write a function named operator+ (and so on). Keep the meaning natural: + should add, == should compare.

Why overload operators?

For built-in types, a + b and a == b just work. For your own class, say Money, you would otherwise write add(a, b) and equals(a, b), which is clumsy. Operator overloading lets you define what +, -, ==, <, << and others mean for your type. The standard library uses it everywhere: std::string has + and ==, std::cout has <<, iterators have ++ and *.

A Money type

cpp
#include <iostream>

class Money {
public:
    explicit Money(long long paise = 0) : paise_(paise) {}
    long long paise() const { return paise_; }

    Money& operator+=(const Money& other) {     // member: changes this object
        paise_ += other.paise_;
        return *this;
    }
private:
    long long paise_;
};

Money operator+(Money a, const Money& b) {     // non-member, built from +=
    a += b;
    return a;
}

bool operator==(const Money& a, const Money& b) { return a.paise() == b.paise(); }
bool operator<(const Money& a, const Money& b) { return a.paise() < b.paise(); }

std::ostream& operator<<(std::ostream& out, const Money& m) {
    return out << "Rs " << m.paise() / 100 << '.' << (m.paise() % 100) / 10 << m.paise() % 10;
}

int main() {
    Money tea(1500), samosa(2000);
    Money bill = tea + samosa;
    std::cout << bill << '\n';                   // Rs 35.00
    std::cout << (tea < samosa) << '\n';         // 1
}
operator+= is a member that changes the object; operator+ is a free function that returns a new value. << returns the stream so you can chain.

Member or non-member?

  • Operators that change the object (+=, -=, ++, =, []) are usually members.
  • Symmetric operators (+, -, ==, <) are usually non-members, so conversions work on both sides the same way.
  • operator<< for printing must be a non-member, because the left side is std::ostream, not your class.
  • = (assignment), [] (subscript), () (call) and -> must be members.

C++20: the spaceship operator

cpp
#include <compare>

struct Version {
    int major, minor;
    auto operator<=>(const Version&) const = default;   // also generates ==
};

// Version{1, 2} < Version{1, 10} is true; ==, !=, <, <=, >, >= all work
operator<=> (three-way comparison) with = default compares members in order and gives all six comparisons.

Increment and subscript

cpp
class Counter {
public:
    Counter& operator++() { ++n_; return *this; }        // prefix: ++c
    Counter operator++(int) { Counter old = *this; ++n_; return old; }   // postfix: c++
    int value() const { return n_; }
private:
    int n_ = 0;
};

class Marks {
public:
    int& operator[](std::size_t i) { return data_[i]; }
    const int& operator[](std::size_t i) const { return data_[i]; }
private:
    int data_[5] = {};
};
The dummy int parameter tells postfix ++ apart from prefix. operator[] usually comes in a const and a non-const version.
Think of it like this: Overloading an operator is like the "+" button on a calculator app that also works for time: 1 h 50 min + 20 min = 2 h 10 min. The symbol stays the same, but its meaning fits the kind of thing you are adding.

Rules and good taste

  • You cannot invent new operators (no **), change precedence, or overload operators for built-in types only (int + int).
  • A few operators cannot be overloaded at all: ::, ., .* and ?:.
  • Keep meanings unsurprising. Using + to delete a file would compile, but nobody could read your code.
  • If you define ==, define != (C++20 generates != from == for you). If you define <, define the others, or just use <=>.
Careful: Do not overload && or ||. Built-in && and || short-circuit (stop early), but overloaded versions always evaluate both sides, which surprises readers. The same goes for the comma operator.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Operator overloading · 1/6

Operator overloading

Operator overloading lets your own types use plus, equals, less-than and the output arrows.

Prefer a video by a teacher? Find free videos on “c++ operator overloading tutorial operator<< operator+ spaceship” on YouTube ↗

In real life: GPS distance and time in a delivery app

A food delivery app adds up travel times for each leg of a rider's route. A small Duration type with + and < lets the code read like the business rule: if (pickup + drive < promised) show "on time". The standard library's std::chrono::duration types work exactly this way.

cpp
#include <chrono>
#include <iostream>

int main() {
    using namespace std::chrono_literals;
    auto pickup = 8min;
    auto drive = 17min;
    auto promised = 30min;
    auto total = pickup + drive;                 // operator+ on durations
    std::cout << total.count() << " min, "
              << (total < promised ? "on time" : "late") << '\n';   // 25 min, on time
}
std::chrono overloads + and < so time arithmetic reads naturally.

Practice (0/4 done)

Task 1 · Question

What is the name of the function that defines a + b for your type?

Task 2 · Question

Why must operator<< for printing be a non-member function?

Task 3 · Question

Which operator can NOT be overloaded?

Task 4 · Practice

Write a struct Fraction { long long num, den; } with operator+, operator== (compare after reducing with std::gcd from <numeric>), and operator<< that prints like 3/4. Test that 1/2 + 1/4 prints 3/4 and that 2/4 == 1/2.

Quick quiz

Question 1

1.Which operators usually are member functions?

Question 2

2.What does auto operator<=>(const T&) const = default; give you?

Question 3

3.How is postfix c++ told apart from prefix ++c when overloading?

Question 4

4.Why avoid overloading &&?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

Which operators usually are member functions?

Answer: +=, =, [] and ++

Operators that modify the object, plus =, [] and (), are members.

What does auto operator<=>(const T&) const = default; give you?

Answer: All six comparison operators, comparing members in order

Defaulted <=> generates <, <=, >, >= and also == / !=.

How is postfix c++ told apart from prefix ++c when overloading?

Answer: Postfix has a dummy int parameter

operator++(int) is postfix; operator++() is prefix.

Why avoid overloading &&?

Answer: The overloaded version always evaluates both sides, losing short-circuit behaviour

Readers expect && to stop early; overloads cannot do that.

What does const after a member function's brackets mean?Related

Answer: It promises not to change the object

A const member function can be called on const objects and cannot modify members.

From Classes and objects: data plus behaviour

What does the rule of three say?Related

Answer: If a class needs a custom destructor, copy constructor or copy assignment, it probably needs all three

These three manage the same resource, so they come as a set.

From Copying objects: the rule of three, five and zero

What does the | operator do between views?Related

Answer: Chains view steps into a pipeline

Range adaptors compose with the pipe operator.

From C++20 ranges, views and other C++20 essentials

When does the compiler choose which overload to call?Related

Answer: At compile time, from the argument types

Overload resolution happens while compiling, based on the arguments in each call.

From Overloading, default arguments and recursion

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 3 more topics in “Operator overloading, inheritance and polymorphism” before its exam: Inheritance: building on an existing class, Virtual functions and polymorphism, Abstract classes, interfaces and good class design.
  2. Module 5 exam: Operators, inheritance and polymorphism · 13 questions · 25 min, without help. 4 topics of this module still to finish first.
  3. Then the next module, The Standard Template Library (STL). 42 topics left in the course before the final exam.

← Previous: Copying objects: the rule of three, five and zero