This lesson is a quick introductory tour of operator overloading within C++. It is not intended for those who are entirely new to programming. Rather, the people who may find it useful include:
It summarises several lessons from our introductory course. Anyone looking for more thorough explanations or additional context should consider Chapter 8 of that course.
We can overload operators like +
and *=
for our custom types. Operators are implemented in the same way as functions, with a specific naming convention.
For example, if we had a custom type called Vector, and we wanted to give Vectors the ability to be added to other Vectors using the +
operator, we would define a function called operator+
as follows:
Vector operator+(const Vector& a,
const Vector& b){
return Vector{
a.x + b.x, a.y + b.y, a.z + b.z};
}
Vector a { 1.f, 2.f, 3.f };
Vector b { 1.f, 1.f, 1.f };
// { 2.f, 3.f, 4.f }
Vector Sum { a + b };
Operators can also be implemented as part of the struct or class that defines our type:
struct Vector {
float x;
float y;
float z;
Vector operator*(float Multiplier){
return Vector{
x * Multiplier,
y * Multiplier,
z * Multiplier
};
}
};
Vector a { 1.f, 2.f, 3.f };
// { 2.f, 4.f, 6.f }
Vector Result { a * 2.f };
Multiple operators can have the same function name. For example, operator-
can be a binary operation, ie, it operates on two objects. This would normally be used to represent arithmetic subtraction (eg VectorA - VectorB
)
But, -
can also be a unary operator, acting upon only one object. This would normally be used for negation (eg, -VectorA
)
The compiler can infer whether we are overloading a unary or binary operator from the number of parameters.
#include <iostream>
struct Vector {
float x;
float y;
float z;
Vector operator-(){
std::cout << "Unary - \n";
return Vector{-x, -y, -z};
}
Vector operator-(const Vector& Other){
std::cout << "Binary - \n";
return Vector{
x - Other.x,
y - Other.y,
z - Other.z
};
}
};
Vector operator+(const Vector& a){
std::cout << "Unary + \n";
return a;
}
Vector operator+(const Vector& a,
const Vector& b){
std::cout << "Binary + \n";
return Vector{
a.x + b.x, a.y + b.y, a.z + b.z};
}
int main(){
Vector A;
-A;
A - A;
+A;
A + A;
}
Unary -
Binary -
Unary +
Binary +
this
PointerFor many operators, such as ++
and *=
, it is expected that the operator will return a reference to the object it operated on. This is important for allowing operators to be chained on our object, in expressions such as (MyObject *= 2) *= 3
. With statements like this, we want subsequent operators to act upon the original object, not a copy of it.
Our previous examples didn’t allow this. However, within a class or struct function, the this
keyword returns a pointer to the current object - that is, the object that the function or operator was called upon. Therefore, we can use this to ensure our operators return the exact same object they were used on:
#include <iostream>
struct Vector {
float x;
float y;
float z;
Vector& operator*=(float Multiplier){
x *= Multiplier;
y *= Multiplier;
z *= Multiplier;
return *this;
}
};
int main(){
Vector A{1.f, 1.f, 1.f};
(A *= 2) *= 3;
std::cout << A.x;
}
x component: 6
Operators like --
and ++
can be used either before or after their operand, and each usage has different behavior.
For example, ++MyInteger
would increment the integer and return it. MyInteger++
would increment the integer but return a different integer, which has the value of our original integer before it was incremented.
For our custom types, overloading the prefix ++
works as expected:
struct Vector {
float x;
float y;
float z;
// ++MyVector (Prefix Operator)
Vector& operator++(){
++x;
++y;
++z;
return *this;
}
};
Overloading the postfix operator has a slightly inelegant syntax. To let the compiler distinguish between which function handles the prefix operator and which handles the postfix, we add an extra unused int
parameter to the postfix handler:
#include <iostream>
struct Vector {
float x;
float y;
float z;
// ++MyVector (Prefix Operator)
Vector& operator++(){
std::cout << "Prefix ++ \n";
++x;
++y;
++z;
return *this;
}
// MyVector++ (Postfix Operator)
Vector operator++(int){
std::cout << "Postfix ++ \n";
Vector Original{x, y, z};
++x;
++y;
++z;
return Original;
}
};
int main(){
Vector A;
++A;
A++;
}
Prefix ++
Postfix ++
Later in this course, we cover a range of further abilities we can add to our custom types. This includes how we can:
()
to let our custom types act like functions (functors).<=
and !=
— First Published
Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games