Lesson 202 +10 XP

Operator Overloading

Operator Overloading

Operator overloading teaches operators like + and << to understand your own types. It makes user-defined types feel like built-ins.

The operators are function calls

a + b;          // compiler reads: operator+(a, b)

Define operator+ for your class and the + between objects starts to work.

Overload operator+

struct Vector {
    int x, y;

    Vector operator+(const Vector& b) const {
        return { x + b.x, y + b.y };
    }
};

Vector v1{1, 2}, v2{3, 4};
Vector r = v1 + v2;   // {4, 6}

The member overload is called as v1.operator+(v2).

Overload the output operator

Stream output is usually a friend function, because it must read the private parts:

struct Vector {
    int x, y;

    friend std::ostream& operator<<(std::ostream& out, const Vector& v) {
        return out << "(" << v.x << ", " << v.y << ")";
    }
};

std::cout << r;   // prints (4, 6)

Which operators can you overload?

Almost any: +, -, ==, <, [], <<, and more. Some, like . and ?:, cannot be overloaded. The kind of arguments must match the operator's natural use.

Why overload

  • Readability: v1 + v2 is natural.
  • Types like strings or vectors use it for a reason.
  • Overloading < lets std::sort order your objects.
struct Student {
    std::string name;
    int grade;
    bool operator<(const Student& o) const {
        return grade < o.grade;
    }
};

TL;DR

  • Overloading gives operators a meaning on your types.
  • Implement operator+ as a member or free function.
  • operator<< is often a friend to reach private data.
  • Overloading < makes std::sort work on your type.
  • Keep overloads intuitive; an operator that surprises is a bug.