---
title: 'Operator Overloading'
source: 'https://academia.sh/en/courses/cpp-fundamentals/operator-overloading'
course: 'C++ Fundamentals and Object Design'
language: en
updated: '2026-09-26T03:02:45+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Measures that operator+ returns a new temporary object'
    - 'Distinguishes that operator+= modifies its own object and returns it by reference'
    - 'Applies limits when deciding which operators are meaningful for a class'
---

# Operator Overloading

Measures why operator+ returns a new temporary object, and why operator+= instead returns its own object by reference.

This is the last lesson in this section of K04. The previous lesson measured that a reference works with the caller's own object without producing any copy. This lesson measures that an **operator** sometimes does exactly the opposite — it produces a new object. The measurement kind is **temporary**: the result of the expression `a + b` is neither `a` nor `b`; it is a new `Money` object, constructed inside the operator's body, that ceases to exist at the end of the expression.

In C, the only way to add such values was a function with an explicit name: a function like `Money add_up(Money a, Money b)` was called, and its result was assigned to a separate variable — writing `a + b` was not possible, because `+` was defined only for the built-in numeric types. In C++, overloading `operator+` opens up the `+` syntax for a user-defined type like `Money` too; the caller writes `a + b` instead of `add_up(a, b)`. This increases the readability of the syntax, but it also hides what the body does (whether it constructs a new object or modifies an existing one) — this is exactly what this lesson's measurement uncovers: which object is produced behind the operator's syntax.

## What Operator Overloading Is

**Operator overloading** is defining what a built-in operator such as `+`, `==`, or `<<` means for a user-defined class. When `operator+` is written as a member function, the expression `a + b` is read by the compiler as `a.operator+(b)` — the syntax stays `+`, but what gets called is a function the class itself writes. Overloading does not add a new syntax; it **gives meaning** to the existing operator syntax for user-defined types.

Overloading cannot change how **many arguments** an operator takes, or its **precedence** — `+` always stays binary, and it continues to be evaluated after `*`. The only thing that can change is what the operator does with its arguments. This limit is deliberate: someone calling `operator+` expects the "takes two values and produces a result" behavior for `Money`, just as for `int`; overloading cannot make a syntactic change that breaks this expectation, it can only define what the "result" and "modification" part means.

```cpp
// money.hpp — a class holding an amount in cents, for operator overloading
#ifndef MONEY_HPP
#define MONEY_HPP

#include <cstdio>

class Money {
public:
    explicit Money(long cents) : cents_(cents) {}

    Money operator+(const Money& other) const {
        return Money(cents_ + other.cents_);
    }

    Money& operator+=(const Money& other) {
        cents_ += other.cents_;
        return *this;
    }

    bool operator==(const Money& other) const {
        return cents_ == other.cents_;
    }

    long cents() const { return cents_; }

private:
    long cents_;
};

inline void use_money(const Money& m) {
    std::printf("cents=%ld\n", m.cents());
}

#endif
```

## `operator+`: Returns a New Temporary

```cpp
// plus-measurement.cpp — is the result of a + b a new temporary
#include <cstdio>

#include "money.hpp"

int main() {
    Money a(100);
    Money b(250);

    Money c = a + b;

    std::printf("is c the same object as a %s\n", &c == &a ? "yes" : "no");
    std::printf("is c the same object as b %s\n", &c == &b ? "yes" : "no");
    use_money(a);
    use_money(b);
    use_money(c);
    return 0;
}
```

```text
is c the same object as a no
is c the same object as b no
cents=100
cents=250
cents=350
```

**CR15.** The expression `a + b` turns into the call `a.operator+(b)`; the body of `operator+`, `return Money(cents_ + other.cents_);`, constructs a **new** `Money` and returns it **by value** — it modifies neither `a` nor `b`, and both keep their own `cents_` value (`100` and `250`). The returned object is constructed into `c`; `c`'s address is neither the same as `a`'s nor as `b`'s. `operator+` being marked `const` (`operator+(const Money& other) const`) guarantees that neither `other` nor the object it is called on (`this`) is modified — by definition, an addition operator must produce only the result, not the operands being added.

## `operator+=`: Modifies Its Own Object and Returns It by Reference

```cpp
// plus-equals-measurement.cpp — does a += b modify a itself
#include <cstdio>

#include "money.hpp"

int main() {
    Money a(100);
    Money b(250);

    Money& result = (a += b);

    std::printf("is result the same object as a %s\n", &result == &a ? "yes" : "no");
    use_money(a);
    return 0;
}
```

```text
is result the same object as a yes
cents=350
```

**CR16.** The body of `operator+=`, `cents_ += other.cents_;`, modifies its **own** `cents_` member, then `return *this;` returns **itself** by reference — it constructs no new object. When `a += b` is called, `a` itself changes (it becomes `350`), and the result of `(a += b)` is again `a` itself: `&result == &a` is true. This is the exact opposite of `operator+`: `operator+` produces a new **temporary** without modifying either operand, while `operator+=` modifies a single object (the left one) and returns a reference of kind **self**. The two operators' return types carry this difference in their signature — `operator+` returns by value (`Money`), `operator+=` by reference (`Money&`); reading the signature alone tells in advance which one produces a new object and which one modifies an existing one.

## The Limits of Defining a Meaningful Operator

The fact that an operator can be overloaded for a user-defined class does not mean every class must define every operator. A few conventions keep operator definitions consistent:

- **Binary arithmetic operators like `+`, `-`, `*`** are usually written as **free functions**, not members (`Money operator+(const Money& a, const Money& b)`), because this provides symmetric conversion for expressions whose left side is not `Money` either (for example, if an `int` were to be added to a `Money` in the future). `Money` defines `operator+` as a member for this lesson's measurement; the free-function form is only mentioned here.
- **`+` can be written in terms of `+=`**: instead of `cents_ + other.cents_`, the body of `operator+` could also be written as `Money result(cents_); result += other; return result;` — basing `+` on `+=` without repeating `+=`'s logic prevents the two operators' behavior from drifting apart. `Money` writes the two independently to keep this lesson's measurement simple.
- **`==` is an equality**, not an ordering; `Money::operator==` compares the two objects' `cents_` values, and an ordering operator like `<` is not defined in this lesson.
- **`<<` (stream output) cannot be a member function** — in the expression `std::cout << m`, the left side is `std::ostream`, not `Money`; that is why `operator<<` is written as a free function, and if it needs to access `Money`'s `private` member, access is granted with a `friend` declaration (mentioned only by name in lesson 02). This lesson does not define `operator<<`; it does the same job with an ordinary function named `use_money`.

The question that must be asked when overloading an operator is this: does this operator's built-in meaning (`+` adds, `==` compares, `<<` prints) still feel **natural** for the class? For `Money`, `+` meaningfully matches addition and `==` meaningfully matches equality; but, for example, `Money operator*(const Money& a, const Money& b)` could be left undefined, because multiplying two amounts has no monetary meaning — this lesson does not write such an operator.

Violating this limit compiles, but it makes the code unreadable. C++ enforces no rule about which meaning an operator must be used with — technically, a subtraction could be written into the body of `operator+`, and the compiler would not object. But such code separates what everyone who writes `a + b` expects ("it is adding") from what actually happens ("it is subtracting") — this is a design flaw that misleads the class's user, and its error cannot be caught at compile time. The only thing that limits the power of overloading is not the compiler, but the discipline of staying faithful to the expectation an operator raises in the reader.

## Where `explicit`, the Copy Constructor, and Operators Meet

`Money`'s constructor is defined as `explicit Money(long cents)` — the `explicit` rule from lesson 03 applies here too: an implicit conversion like `Money m = 100;` does not compile, and `Money m(100);` or `Money m{100};` must be written instead. This interacts directly with operator overloading: the line `return Money(cents_ + other.cents_);` inside `operator+`'s body writes an **explicit** construction; if the constructor were not `explicit` and the body wrote `return cents_ + other.cents_;`, the `long` result could be implicitly converted into a `Money` — this would open the door to exactly the kind of unwanted implicit conversion chain lesson 03 warned about (for example, a `Money` being compared, indirectly and by mistake, with a `long`). `operator+`'s result is always returned by explicitly constructing a `Money`; this both follows the `explicit` rule and keeps what the operator produces explicit in the code. The copy constructor from lesson 05 also comes into play here implicitly: when the line `return Money(...)` returns a new `Money` value, the compiler, in most cases, constructs this value directly into the place the caller will receive it (an optimization that skips the value copy), but the conceptual model is still "a new object was constructed and returned" — the copy constructor never being called is an optimization detail, and it does not change the fact that `operator+` produces a new object.

## Value Semantics: This Course's Context

M11/K01 showed that a struct is copied field by field on assignment; this is value semantics: when a value is assigned or passed, the two sides become independent of each other. `Money` applies this principle with C++'s own tools — the copy constructor, copy assignment, and now `operator+` returning a new value. `operator+=`, by contrast, deliberately steps outside this principle: it modifies its own object, because `+=`'s built-in meaning is already "update the value on the left" (`x += 1` also modifies `x`, it does not construct a new variable). Which of these two behavior patterns is chosen when writing an operator for a class must stay consistent with the behavior of the operator's built-in `int`/`long` counterpart — `Money` preserves this consistency: `+` produces a new value, `+=` modifies the existing one, exactly as for `int`.

## Summary of the Copy, Temporary, and Self Distinction

This topic's seven lessons measured a single question from different angles: which object does an expression work with? Lessons 03 and 04 measured how an object acquires its own resource (constructor, destructor, RAII); lesson 05 measured how a copy separates from its original (**copy**); lesson 06 measured how a reference works with the caller's **self** without any copying; and this lesson measured when an operator produces a new **temporary**, and when it modifies its own object and returns **itself**. The four kinds — **self**, **copy**, **part**, **temporary** — correspond to the single question to ask when reading a C++ expression: which other object is the object this expression produces or operates on the same as, and which is it different from?

## The Bounding Measurement

```cpp
// chain-measurement.cpp — how many temporaries does a + b + c produce
#include <cstdio>

#include "money.hpp"

int main() {
    Money a(10);
    Money b(20);
    Money c(30);

    Money total = a + b + c;

    use_money(total);
    return 0;
}
```

```text
cents=60
```

**CR17.** The expression `a + b + c` is evaluated left to right: first `a + b` runs and produces an unnamed `Money` with the value `cents_=30`; then this result becomes the left side of the `+ c` call. Because `operator+` is a member function, the second call's `this` must point to an object: for this reason, the result of `a + b` is constructed as **one temporary** and lives until the full expression (the end of `a + b + c;`, the semicolon) finishes, then is destroyed. The second `operator+` call's result, with the value `cents_=60`, is not constructed as a separate temporary: under C++17's guaranteed copy elision, it is constructed directly in `total`'s own storage. Two `operator+` calls therefore produce **one** temporary; `total` is the very result of the second call itself, not a copy of it. Because `Money`'s destructor does not contain a `printf` here, the moment the temporary is constructed and destroyed is not observable in this block; the count is read from the language's rule, not from this measurement. The answer to the question of "how many temporaries" a chained addition produces depends not so much on how many times the operator is called, but on where each result goes: an intermediate result that becomes the object of the next call is a temporary, while a final result that initializes a variable is that variable itself.

## Summary

- The expression this lesson measures is of kind **temporary**: `operator+` returns a new, unnamed `Money` without modifying the operands; its return type is by value (`Money`, not a reference).
- `operator+=` modifies its own object and returns **itself** (`*this`) by reference; its return type is `Money&`.
- Binary arithmetic operators are usually written as free functions; `<<` cannot be a member function because its left side is not the class itself.
- An operator should be defined only when its built-in meaning is natural for the class.
- In a chained expression (`a + b + c`), only the intermediate result (`a + b`) is constructed as a temporary and lives until the full expression finishes; the final result is constructed directly inside `total`.
- This topic's seven lessons asked the same question: does a C++ expression work with a **self**, **copy**, **part**, or **temporary** object?

## Next Step

This topic measured how an object acquires its own resource, is copied, is passed by reference, and produces new objects through operators. The next topic moves away from this single-object model to the **relationship** between classes — how a class extends another class's behavior, and how it is determined at run time which function gets called.
