Operator Overloading¶
Syntax¶
Assumptions: a
and b
are operands; @
is the placeholder for the
operator, not the @
operator
Expression |
As method |
As function |
---|---|---|
|
|
|
|
|
|
Operators that can be overloaded
+ - * / % ^ & | ~ ! = < > += -= *= /= %= ^= &= |= << >> >>= <<= == != <= >= && || ++ -- , ->* ->
Operator overloading as methods¶
Only when
a
is a class-typed objectDeclare as a method in the class of the object
a
Declare as
const
method to makea
constDeclare
b
as a const formal parameter to makeb
1class Point {
2 int x;
3 int y;
4 public:
5 Point()=default;
6 Point(int x, int y): x(x), y(y) {}
7 Point operator+(const Point& other) const {
8 return Point(x + other.x, y + other.y);
9 }
10 // binary - operator
11 Point operator-(const Point& other) const {
12 return Point(x - other.x, y - other.y);
13 }
14 // Unary - operator
15 Point operator-() const {
16 return Point(-x, -y);
17 }
18 // better to make it const! Check the warning after
19 bool operator==(const Point& other) const {
20 return x == other.x && y == other.y;
21 }
22 void print() const {
23 cout << "X: " << x << " Y: " << y << endl;
24 }
25};
26
27int main() {
28 Point p1(10, 5), p2(2, 1);
29 Point p3 = p1 + p2;
30 Point p4 = p1 - p2;
31 p3.print();
32 (-p3).print();
33 p4.print();
34 if (p1 == p2) cout << "P1 equals P2" << endl;
35 else cout << "P1 not equal P2" << endl;
36 return EXIT_SUCCESS;
37}
Operator overloading as functions¶
a
andb
can be any typeDeclare
a
andb
as a const formal parameters to make them constmay be declared as a
friend
function of a class to access private instance variables
1class Point {
2 int x;
3 int y;
4 public:
5 Point()=default;
6 Point(int x, int y): x(x), y(y) {}
7 void print() const {
8 cout << "X: " << x << " Y: " << y << endl;
9 }
10 // binary +
11 friend Point operator+(const Point& p1, const Point & p2) {
12 // will need public getter for x and y if not defined as a friend method
13 // return Point(p1.getX() + p2.getX(), p1.getY(), p2.getY()
14 return Point(p1.x + p2.x, p1.y + p2.y);
15 }
16 // binary -
17 friend Point operator-(const Point& p1, const Point & p2) {
18 return Point(p1.x - p2.x, p1.y - p2.y);
19 }
20 // Unary - operator
21 friend Point operator-(const Point &p1) {
22 return Point(-p1.x, -p1.y);
23 }
24 friend bool operator==(const Point& p1, const Point & p2) {
25 return p1.x == p2.x && p1.y == p2.y;
26 }
27};
28
29int main() {
30 Point p1(10, 5), p2(2, 1);
31 Point p3 = p1 + p2;
32 Point p4 = p1 - p2;
33 p3.print();
34 (-p3).print();
35 p4.print();
36 if (p1 == p2) cout << "P1 equals P2" << endl;
37 else cout << "P1 not equal P2" << endl;
38 return EXIT_SUCCESS;
39}
Const¶
It is a great practice to make everything const
if possible. For instance,
operators like arithmetic, relational, logical operators can usually be made
const. Some operators like ++/--
, =
, +=
, etc. cannot be const as
they must modify the internal state of the object.
Warning
==
operator used in Catch2 tests with REQUIRE
or CHECK
macros
must be const. Unless it is protected with extra pair of parenthesis.
CHECK(p1 == p2); // requires == operator to be const
CHECK((p1 == p2)); // does not require == operator to be const
Best Practice¶
Do not abuse operator overloading. Only use it when it is logically making sense. Anything that may surprise the user should be avoided.