Post

Operator Overloading

Operator Overloading

Operator Overloading in C++


Prerequisites


1. What is Operator Overloading

Operator overloading allows you to define custom behavior for operators (+, -, *, ==, etc.) on user-defined types.

CategoryOperators
Arithmetic+ - * /
Comparison== != < > <= >=
Assignment= += -=
Increment++ --
Access[] () ->
Stream<< >>

Makes code more intuitive and expressive.

✔ Without overloading
1
Vector c = add(a, b);
✔ With overloading
1
Vector c = a + b;

Cleaner and closer to mathematical notation

2. Operator Overloading

2-1. Basic Syntax

1
2
3
4
return_type operatorOP(parameters) 
{
    // implementation
}

Example:

1
2
3
4
5
6
7
8
9
10
class Vec 
{
public:
    int x, y;

    Vec operator+(const Vec& other) const 
    {
        return {x + other.x, y + other.y};
    }
};

2-2. Member/Non-member

✔ Member function
1
Vec operator+(const Vec& other) const;

Left operand = object itself

✔ Non-member (free function)
1
Vec operator+(const Vec& a, const Vec& b);

More flexible (especially for symmetry)

CaseRecommendation
Access private membersMember or friend
Symmetric operationNon-member
Assignment-like (=)Member

2-3. Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Vec 
{
public:
    Vec(float x, float y) : x(x), y(y) {}

    Vec operator+(const Vec& other) const 
    {
        return Vec(x + other.x, y + other.y);
    }

    Vec operator*(float scalar) const 
    {
        return Vec(x * scalar, y * scalar);
    }

public:
    float x, y;
};
Stream Operator (<<)
✔ Must be non-member
1
2
3
4
5
6
7
#include <iostream>

std::ostream& operator<<(std::ostream& os, const Vec& v) 
{
    os << "(" << v.x << ", " << v.y << ")";
    return os;
}
Comparison Operator
1
2
3
4
bool operator==(const Vec& other) const 
{
    return x == other.x && y == other.y;
}
Assignment Operator
1
2
3
4
5
6
7
8
9
10
Vec& operator=(const Vec& other) 
{
    if (this != &other) 
    {
        x = other.x;
        y = other.y;
    }

    return *this;
}

Must return reference

Increment Operator
✔ Prefix
1
2
3
4
5
6
Vec& operator++() 
{
    x++; y++;

    return *this;
}
✔ Postfix
1
2
3
4
5
6
Vec operator++(int) 
{
    Vec temp = *this;
    ++(*this);
    return temp;
}

int is dummy parameter

Subscript Operator
1
2
3
4
5
6
7
int& operator[](int index) 
{
    if (index == 0) 
        return x;

    return y;
}
Function Call Operator
1
2
3
4
5
6
7
8
class Functor 
{
public:
    int operator()(int x) 
    {
        return x * x;
    }
};
+Performance Considerations
Return by value (C++17 optimized)
1
2
3
4
Vec operator+(const Vec& other) const 
{
    return Vec(x + other.x, y + other.y);
}

Copy elision / move optimization

  • Use const& for parameters
  • Return by value (optimized)
✔ DO
  • Keep semantics intuitive
  • Use const correctness
  • Prefer non-member for symmetric ops
  • Keep operators lightweight
❌ DON’T
  • Overload in confusing ways
  • Hide expensive operations behind operators
  • Break expected behavior
Bad Example: unexpected behavior
1
2
3
4
5
Vec operator+(const Vec& other) 
{
    sleep(1);  // ❌ unexpected behavior
    return ...
}
This post is licensed under CC BY 4.0 by the author.