Unary and binary operators, equality, comparison, subscript, function operator, user-defined literals, and move assignment.
Unary operators act on a single operand. Examples: ++, --, *, &, !, ~, -, +, and conversion operators.
They can be defined as static/global functions or non-static class members:
// Takes the operand as a parameter
ReturnType operator~(MyType param);
// No parameter — operates on *this
ReturnType operator~();
Member unary operators operate on themselves using *this. For post-increment, the compiler passes a dummy int parameter to distinguish it from pre-increment:
class Date {
public:
Date& operator++(); // pre-increment: ++d
Date operator++(int); // post-increment: d++ (dummy int param)
};
Binary operators act on two operands. Examples: &, +, -, /, *, %, !=, +=, -=, *=, /=, =, <<, >>, [].
// Both operands are parameters
Ret operator+(T lhs, T rhs);
// Left operand is *this
Ret operator+(T rhs);
class Date {
public:
// Member: left side is *this, right side is parameter
Date operator+(int days);
};
Date myDate;
Date later = myDate + 5; // myDate.operator+(5)
+=, -=, etc.) since they naturally modify *this.Without an overloaded ==, the compiler performs a binary bitwise comparison by default — which is usually not what you want for class types.
class Date {
public:
bool operator==(const Date& other) const {
// compare the fields that define equality
return day == other.day && month == other.month && year == other.year;
}
};
==, you can implement != for free by inverting it:return !(this->operator==(other));<, >, <=, >=)To support full ordering, you need to overload all four comparison operators. As with !=, you can often derive them from each other to reduce duplication.
operator<=> (the "spaceship operator") and the compiler automatically generates all six comparison operators from it.The copy assignment operator (operator=) modifies an existing object to match another. Always guard against self-assignment:
Student& operator=(const Student& source) {
if (this != &source) { // self-assignment guard
// copy source's members into *this
}
return *this; // enables chaining: a = b = c
}
a = a could free the object's own memory before copying it — causing a crash.The subscript operator (operator[]) lets a class behave like an array. You should provide both a mutable and a const version:
class Container {
public:
// Non-const: caller can modify the returned element
char& operator[](int index);
// Const: protects both the returned ref and the class members
const char& operator[](int index) const;
};
The trailing const on the method prevents the function from modifying any class member values. The leading const on the return type prevents the caller from modifying the returned reference.
operator() lets a class instance be called like a function. Such objects are called functors or function objects. The parameter list and return type can be anything:
class Multiplier {
public:
int operator()(int a, int b) const {
return a * b;
}
};
Multiplier mul;
mul(3, 4); // same as mul.operator()(3, 4) → 12
Certain workflows — returning a value from a function, passing a temporary — can result in unnecessary calls to the copy constructor. C++11 compilers try to use the move constructor/operator instead if one is implemented, stealing resources rather than copying them:
// Move constructor
Sample(Sample&& source) noexcept;
// Move assignment operator
Sample& operator=(Sample&& source) noexcept;
Both use an rvalue reference (&&). The source is left in a valid but unspecified state after the move (typically empty/null). The structure is similar to copy/assignment — check for self-assignment, transfer ownership, nullify the source.
A conversion operator allows a class to implicitly (or explicitly) convert to another type. The syntax uses operator followed by the target type — no return type is written:
class Temperature {
public:
operator double() const { // converts Temperature → double
return celsius;
}
private:
double celsius;
};
Temperature t;
double d = t; // implicit conversion via operator double()
explicit keyword to require an explicit cast instead:explicit operator double() const;double d = t is a compile error; double d = (double)t or static_cast<double>(t) is required.User-defined literals let you attach meaning to numeric or string literals using a suffix. The operator name must start with an underscore:
// Converts a long double to a Temperature in Celsius
Temperature operator""_C(long double celsius) {
return Temperature(celsius);
}
Temperature boiling = 100.0_C; // calls operator""_C(100.0)
unsigned long long, long double, const char*, etc. You cannot use arbitrary types as the raw parameter.1s (1 second), "hello"s (std::string), and 1i (imaginary number). Suffixes without a leading underscore are reserved for the standard library.