Operator overloading — common interview cases

RoadmapsC++

Scenario

You overload `operator+` as a member function of your `Vector2D` class. While `vec + 5` works perfectly, writing `5 + vec` throws a compiler error.

Why does addition suddenly care about left-to-right order?

Mental model

When an operator is a member function, the left side of the operator IS the object making the call (`vec.operator+(5)`). If the left side is an integer (`5.operator+(vec)`), it fails because integers don't have your class's methods.

Operator overloading allows custom classes to use standard operators like `+`, `==`, or `<<`. The primary pitfall is choosing whether to overload them as member functions or free (non-member) functions. For symmetric operators (like `+` or `*`), you should use non-member `friend` functions so that both the left and right operands are treated equally and can undergo implicit conversions.

Explanation

C++ allows you to overload operators to make custom classes behave like primitives. However, don't overload them to be 'cute' (e.g., using `+` to add an item to a database)—operators should stick to their conventional mathematical or logical meanings.

**Member vs. Non-Member Overloads:**

If you define `operator+` inside a class, the object on the left side of the `+` is the `this` object. This creates an asymmetry: `myObject + 5` is evaluated as `myObject.operator+(5)`, which works. But `5 + myObject` fails because `5` is a primitive and cannot invoke `operator+` on your class.

To achieve mathematical symmetry, binary operators (`+`, `-`, `*`, `==`) must be defined as free (non-member) functions. If they need to access private data, you declare them as `friend` functions inside the class. They take both operands as parameters (usually by `const&`), meaning `5 + myObject` perfectly matches `operator+(5, myObject)`.

**Return Types:**

Operators like `+` create a entirely new object without modifying the originals, so they must return by value. Operators like `+=` modify the existing object and return `*this` by reference (`Type&`).

Code examples

The bug: Asymmetric member operator

#include <iostream>

class Vector2D {
    double x, y;
public:
    Vector2D(double x, double y) : x(x), y(y) {}
    
    // Member operator+
    Vector2D operator+(double scalar) const {
        return Vector2D(x + scalar, y + scalar);
    }
};

int main() {
    Vector2D v(1.0, 2.0);
    Vector2D v1 = v + 5.0; // OK: v.operator+(5.0)
    // Vector2D v2 = 5.0 + v; // ERROR: 5.0 is not a Vector2D!
    return 0;
}

The member operator ties the addition strictly to the `Vector2D` object being on the left side. Commutative math breaks down.

The fix: Symmetric friend function

#include <iostream>

class Vector2D {
    double x, y;
public:
    Vector2D(double x, double y) : x(x), y(y) {}
    
    // Friend free function: defined inside class for convenience, but acts as a global function
    friend Vector2D operator+(const Vector2D& lhs, double scalar) {
        return Vector2D(lhs.x + scalar, lhs.y + scalar);
    }
    
    // Reverse order overload ensures perfect symmetry
    friend Vector2D operator+(double scalar, const Vector2D& rhs) {
        return Vector2D(rhs.x + scalar, rhs.y + scalar);
    }
};

int main() {
    Vector2D v(1.0, 2.0);
    Vector2D v1 = v + 5.0; // OK: operator+(v, 5.0)
    Vector2D v2 = 5.0 + v; // OK: operator+(5.0, v)
    return 0;
}

By using `friend` free functions, we decouple the operator from the `this` pointer. We provide both orderings so that primitive types can safely sit on either side of the `+` operator.

Key points

Common mistakes

Recall questions

Questions & answers

A candidate implements `operator==` as a member function of their `String` class. When they write `if ("hello" == myString)`, the code fails to compile. Why?

The left side is a `const char*`. Since `operator==` is a member function, the compiler tries to call `("hello").operator==(myString)`, which doesn't exist. It should be a free function `bool operator==(const char* lhs, const String& rhs)`.

Approach: Identify the asymmetry of member operators.

How does `operator+=` differ from `operator+` in terms of its return type?

`operator+=` modifies the existing object in place and should return `*this` by reference (e.g., `Class&`). `operator+` creates a new object and must return it by value.

Approach: Understand the difference between mutating and non-mutating operators.

Continue learning

Previous: Classes, constructors, destructors & this

Return to C++ Roadmap