Docs
README
Operator Overloading in C++
Table of Contents
- •Introduction
- •Syntax
- •Arithmetic Operators
- •Comparison Operators
- •Stream Operators
- •Assignment Operator
- •Subscript and Function Call
- •Friend Functions
- •Best Practices
Introduction
Operator overloading lets you define how operators work with your custom types.
Vector v1(1, 2), v2(3, 4);
Vector v3 = v1 + v2; // Uses overloaded +
Overloadable Operators
| Can Overload | Cannot Overload |
|---|---|
+ - * / % | :: . .* |
== != < > <= >= | ?: sizeof |
<< >> | typeid |
= [] () | |
++ -- | |
new delete |
Syntax
As Member Function
class Number {
int value;
public:
Number operator+(const Number& other) const {
return Number(value + other.value);
}
};
As Non-Member (Friend)
class Number {
int value;
friend Number operator+(const Number& a, const Number& b);
};
Number operator+(const Number& a, const Number& b) {
return Number(a.value + b.value);
}
Arithmetic Operators
class Vector {
double x, y;
public:
Vector(double x = 0, double y = 0) : x(x), y(y) {}
Vector operator+(const Vector& v) const { return Vector(x + v.x, y + v.y); }
Vector operator-(const Vector& v) const { return Vector(x - v.x, y - v.y); }
Vector operator*(double s) const { return Vector(x * s, y * s); }
Vector operator/(double s) const { return Vector(x / s, y / s); }
Vector operator-() const { return Vector(-x, -y); } // Unary minus
};
Compound Assignment
Vector& operator+=(const Vector& v) {
x += v.x; y += v.y;
return *this;
}
Increment/Decrement
class Counter {
int value;
public:
Counter& operator++() { ++value; return *this; } // Pre
Counter operator++(int) { Counter t = *this; ++value; return t; } // Post
};
Comparison Operators
class Date {
int year, month, day;
public:
bool operator==(const Date& d) const {
return year == d.year && month == d.month && day == d.day;
}
bool operator!=(const Date& d) const { return !(*this == d); }
bool operator<(const Date& d) const {
if (year != d.year) return year < d.year;
if (month != d.month) return month < d.month;
return day < d.day;
}
bool operator>(const Date& d) const { return d < *this; }
bool operator<=(const Date& d) const { return !(d < *this); }
bool operator>=(const Date& d) const { return !(*this < d); }
};
C++20 Spaceship Operator
#include <compare>
class Date {
auto operator<=>(const Date&) const = default; // All comparisons!
};
Stream Operators
class Point {
int x, y;
public:
friend ostream& operator<<(ostream& os, const Point& p) {
return os << "(" << p.x << ", " << p.y << ")";
}
friend istream& operator>>(istream& is, Point& p) {
return is >> p.x >> p.y;
}
};
// Usage
Point p(3, 4);
cout << p << endl; // (3, 4)
cin >> p; // Input: 5 6
Assignment Operator
Copy Assignment
class String {
char* data;
size_t len;
public:
String& operator=(const String& other) {
if (this != &other) { // Self-assignment check
delete[] data;
len = other.len;
data = new char[len + 1];
strcpy(data, other.data);
}
return *this;
}
};
Move Assignment (C++11)
String& operator=(String&& other) noexcept {
if (this != &other) {
delete[] data;
data = other.data;
len = other.len;
other.data = nullptr;
other.len = 0;
}
return *this;
}
Subscript and Function Call
Subscript []
class Array {
int* data;
size_t size;
public:
int& operator[](size_t i) { return data[i]; }
const int& operator[](size_t i) const { return data[i]; }
};
Function Call ()
class Adder {
int value;
public:
Adder(int v) : value(v) {}
int operator()(int x) const { return x + value; }
};
Adder add5(5);
cout << add5(10); // 15
Friend Functions
Use friend when left operand isn't your class:
class Complex {
double real, imag;
public:
Complex(double r = 0, double i = 0) : real(r), imag(i) {}
// 2.0 * complex needs friend
friend Complex operator*(double d, const Complex& c) {
return Complex(d * c.real, d * c.imag);
}
};
Complex c(1, 2);
Complex r = 2.0 * c; // Works!
Best Practices
✅ Do
// Return reference for compound assignment
T& operator+=(const T& other) { ...; return *this; }
// Implement in terms of compound
T operator+(const T& a, const T& b) { T t = a; return t += b; }
// Const correctness
bool operator==(const T& other) const;
// Self-assignment check
T& operator=(const T& other) {
if (this != &other) { ... }
return *this;
}
❌ Don't
// Don't change expected behavior
T operator+(const T& other) { /* don't subtract! */ }
// Don't overload &&, ||, or comma
T operator&&(const T& other); // Breaks short-circuit
// Don't return references to temporaries
T& operator+(const T& other) { T t = ...; return t; } // Dangling!
Quick Reference
class T {
public:
// Arithmetic
T operator+(const T& r) const;
T& operator+=(const T& r);
T operator-() const; // Unary
T& operator++(); // Pre
T operator++(int); // Post
// Comparison
bool operator==(const T& r) const;
bool operator<(const T& r) const;
// Assignment
T& operator=(const T& r);
T& operator=(T&& r) noexcept;
// Subscript
E& operator[](size_t i);
// Function call
R operator()(Args...);
// Stream (friend)
friend ostream& operator<<(ostream&, const T&);
friend istream& operator>>(istream&, T&);
};
Compile & Run
g++ -std=c++17 -Wall examples.cpp -o examples && ./examples