C++ operator overloading
Give a Vec2 class natural arithmetic, comparison, and output operators.
On this page
C++ classes and const member functions.
- Give a Vec2 class natural arithmetic, comparison, and output operators.
- Predict the sample output and explain the state changes.
- Complete the practice task and check the boundary cases.
The concept
Operator overloading lets a user-defined type work with the usual operators. A 2D vector class can define + and - for vectors, * for scaling, == for comparison, and << for printing. Done well, code such as a + b * 2 reads like the mathematics.
Binary arithmetic operators are usually written as const member functions or as free functions that return a new object. The stream operator << must be a free function because its left operand is the stream. Overload only when the meaning is obvious; an operator that surprises its readers is worse than a named function.
Code example
#include <iostream>
struct Vec2 {
int x;
int y;
Vec2 operator+(const Vec2& other) const { return {x + other.x, y + other.y}; }
Vec2 operator-(const Vec2& other) const { return {x - other.x, y - other.y}; }
Vec2 operator*(int k) const { return {x * k, y * k}; }
bool operator==(const Vec2& other) const { return x == other.x && y == other.y; }
};
std::ostream& operator<<(std::ostream& out, const Vec2& v) {
return out << "(" << v.x << ", " << v.y << ")";
}
int main() {
Vec2 a{1, 2};
Vec2 b{3, 4};
std::cout << a + b << "\n";
std::cout << b - a << "\n";
std::cout << a * 3 << "\n";
std::cout << (a + b == Vec2{4, 6}) << " " << (a == b) << "\n";
}(4, 6) (2, 2) (3, 6) 1 0
Follow the code
Open the walkthrough to inspect the example one step at a time.
Show guided walkthrough
#include <iostream> struct Vec2 { int x; int y; Vec2 operator+(const Vec2& other) const { return {x + other.x, y + other.y}; } Vec2 operator-(const Vec2& other) const { return {x - other.x, y - other.y}; } Vec2 operator*(int k) const { return {x * k, y * k}; } bool operator==(const Vec2& other) const { return x == other.x && y == other.y; }}; std::ostream& operator<<(std::ostream& out, const Vec2& v) { return out << "(" << v.x << ", " << v.y << ")";} int main() { Vec2 a{1, 2}; Vec2 b{3, 4}; std::cout << a + b << "\n"; std::cout << b - a << "\n"; std::cout << a * 3 << "\n"; std::cout << (a + b == Vec2{4, 6}) << " " << (a == b) << "\n";}Follow the example
Start to inspect the source, values, and output. These prepared steps explain the published sample; grouped loop steps describe multiple iterations.
View the complete dry-run table
| Step / line | What happens | State after step | Output so far |
|---|---|---|---|
| a + b calls a.operator+(b) and returns a new vector. const says that a is not changed. | — | — | |
| A free function so that std::cout << v works. It returns the stream so that calls can be chained. | — | — | |
| (1,2) + (3,4). | — | (4, 6) | |
| (3,4) − (1,2). | — | (4, 6) (2, 2) | |
| Scaling by an int. | — | (4, 6) (2, 2) (3, 6) | |
| == compares both fields; a bool prints as 1 or 0. | — | (4, 6) (2, 2) (3, 6) 1 0 |
Behind the scenes
How C++ processes this code
The C++ compiler produces a native executable. Execution enters main, where objects and function calls perform the work.
Cost and common mistakes
Each operator is O(1).
- 3 * a does not compile with a member operator*(int), because the left operand is an int. Add a free function for that order.
- Define == and != together, and keep them consistent. Since C++20, defining == also gives !=, and <=> can generate the comparison operators.
- Do not overload && or ||, and avoid the comma operator: the overloaded versions lose short-circuit behaviour.
Try it yourself
How do you support 3 * a?
Reveal answer and reasoning
Add a free function Vec2 operator*(int k, const Vec2& v) { return v * k; }.