A binary operator can have various calling combinations. Let’s say we want to create a Point
class that has the facility of the following additions: Point + Point
, Point + int
, and int + Point
. C++ allows an operator to be overloaded as a class member and as a non-member of the class. Different aspects should be considered when overloading the operators in C++.
Let’s dive right in!
We’ll cover:
In C++, we can overload an operator in different ways. We use a simple example of the Point
class to represent a point in the Cartesian plane. It has only two data members of the int
type to represent the value of and (in a two-dimensional surface). We also define a constructor that receives two parameters of the int
type to initialize both data members. We have a method, show
, to display the object’s current value. We keep extending the code to illustrate and explain the concepts as we move on, adding various forms of overloading the +
operator for this class and any support elements.
Certainly, C++ knows how to perform the +
operation on the data types defined by the language itself, i.e., all primitive data types. However, it does not know how to perform the +
operation on a data type defined here (the user-defined or abstract data type). Therefore, we need to write the steps of that operation in the form of an overloaded version.
Some operators cannot be overloaded as non-members, e.g., assignment, subscript, and function call operators. Their caller (the first operand or the left-hand-side) cannot be anything other than an object of the same class.
The definition of the operator should have the functionality of adding the corresponding values of two axes of two points. It should also have the ability to add an integer value to both axes. Therefore, it has three possible combinations of operator calls.
The first possibility of calling the +
operator that comes to mind is the ability to add two objects of the same class. In this case, we want to add the corresponding data members of both objects into a new object. If a
, b
, and c
are of type int
, then c = a + b;
does not modify a
and b
. It stores their sum to c
. Similarly, we need to protect the values of operands and return the sum to be stored in another object. If these three variables are the objects of type Point
, then we need c.x = a.x + b.x;
and c.y = a.y + b.y;
.
An operator can be overloaded as a member of the class when the operands are objects of the same class.
Let’s see the complete code for this task.
#include <iostream>using namespace std;class Point {int x, y;public:Point (int a, int b): x(a), y(b) {}void show() const { cout << "(" << x << "," << y << ") ";}Point operator+ (const Point &rhs) const {return Point(x + rhs.x , y + rhs.y);}};int main() {Point p(1,2), q(3,5);p.show();q.show();// The overloaded operator works for Point + PointPoint r = p + q;r.show();// The overloaded operator cannot work for the following// Point s = p + 6;// Point t = 7 + p;return 0;}
Focusing on the overloaded operator in the above code, the first operand (caller object) p
is received as *this
, and the second operand q
is received as the parameter rhs
.
Lines 10–12: We overload the +
operator for the Point
class. The operator+
function takes a constant reference to another Point
object (rhs
) and returns a new Point
object whose x
coordinate is the sum of the x
coordinates of the two points, and the y
coordinate is the sum of the y
coordinates of the two points.
Lines 21–22: We use the overloaded +
operator to add points p
and q
, creating a new Point
object r
. The coordinates of r
are (1 + 3, 2 + 5) = (4, 7). The result is displayed using the show
member function.
Lines 25–26: These lines are commented out to demonstrate that the overloaded +
operator does not work for adding a Point
object and an integer, or an integer and a Point
object, due to the way the operator is defined within the class.
Data Structures Preliminaries (Refresher of Fundamentals in C++)
Dive into a comprehensive review of the fundamental elements of C++ through this course. Experience concise yet detailed explanations, coupled with hands-on exercises that delve into the core concepts of C++ fundamentals. Your journey begins with the exploration of fundamental programming concepts, such as the versatility of variables and their applications in strengthening control structures like conditions, loops, arrays and pointers. Next, you’ll cover structured programming, understanding its advantages and disadvantages, which seamlessly transitions you into object-oriented programming (OOP). Your focus will expand to encompass subjects like classes, object relationships and the implementation of operator overloading to equip user-defined data types. By the end of this course, you'll possess a solid grasp of the essential fundamentals, providing a robust foundation for success in subsequent courses, including the study of data structures and algorithms in C++.
We can invoke the +
operator for c = a + b
where a
is the object of type Point
and b
is a value of type int
. This call cannot invoke the above-defined version because we have defined it for Point + Point
but not for Point + int
. So we need to define a new version where we want to add the value of b
to both data members of a
and return the result as a new object of type Point
.
An operator can be overloaded as a member of the class when the first operand is an object of the same class.
Let’s see the complete code for this task.
#include <iostream>using namespace std;class Point {int x, y;public:Point (int a, int b): x(a), y(b) {}void show() const { cout << "(" << x << "," << y << ") ";}Point operator+ (const int &rhs) const {return Point(x + rhs , y + rhs);}};int main() {Point p(1,2);p.show();// The overloaded operator works for Point + intPoint s = p + 6;s.show();// The overloaded operator cannot work for the following// Point r = p + q;// Point t = 7 + p;return 0;}
Focusing on the overloaded operator in the above code, the first operand (caller object) p
is received as *this
, and the second operand 6
is received as the parameter rhs
.
Lines 10–12: We define the operator+
method. This is an overloaded operator method for addition (+
). It takes a single argument, which is a constant reference to an integer (rhs
for the right-hand side). It returns a new Point
object where the x
and y
coordinates are increased by the value of rhs
.
Lines 20–21: We use the overloaded +
operator to add the integer value 6
to the p
object, creating a new Point
object s
. Then, we call the show
method for s
to display its coordinates.
Lines 24–25: The code in these lines, marked as comments, attempts to use the overloaded +
operator in situations where it’s not defined. The +
operator can work for adding an integer to a Point
object (p + 6
), but it cannot work for adding two Point
objects together (p + q
) or adding a Point
object to an integer (7 + p
).
The user of our class can also invoke c = a + b
where a
is of type int
and b
is an object of type Point
. Again, this call cannot invoke both of the above-defined versions because we define it for Point + Point
and Point + int
, but not for int + Point
. The sequence of data types also matters in case of function overloading in C++. So, we need to define a new version where we want to code the same functionality for a different sequence.
An operator must be overloaded as a non-member when the first operand is not an object of the class.
This version of the +
operator cannot be overloaded as a member of the class because every member function receives the caller object as *this
of the same class type. Therefore, we overload this version as a non-member. Let’s see the complete code for this task.
#include <iostream>using namespace std;class Point {int x, y;public:Point (int a, int b): x(a), y(b) {}void show() const { cout << "(" << x << "," << y << ") ";}friend Point operator+ (const int &lhs, const Point &rhs);};Point operator+ (const int &lhs, const Point &rhs) {return Point(lhs + rhs.x , lhs + rhs.y);}int main() {Point p(1,2);p.show();// The overloaded operator works for int + PointPoint t = 7 + p;t.show();// The overloaded operator cannot work for the following// Point r = p + q;// Point s = p + 6;return 0;}
In the above code:
Line 10: We declare a friend function operator+
inside the Point
class. This is an overloaded operator method for addition (+
). It takes an integer (lhs
for the left-hand side) and a constant reference to a Point
object (rhs
for the right-hand side) as arguments. Declaring it as a friend function allows it to access the private members of the Point
class.
Lines 13–15: We define the operator+
function outside the class. It takes an integer lhs
and a constant reference to a Point
object rhs
. Inside the function, it creates and returns a new Point
object where the x
coordinate is the sum of lhs
and rhs.x
, and the y
coordinate is the sum of lhs
and rhs.y
.
Lines 22–23: We use the overloaded +
operator to add the integer value 7
to the p
object, creating a new Point
object t
. Then, we call the show
method for t
to display its coordinates.
Lines 26–27: The code in these lines, marked as comments, attempts to use the overloaded +
operator in situations where it’s not defined. The +
operator can work for adding an integer to a Point
object (7 + p
), but it cannot work for adding two Point
objects together (p + q
) or adding an integer to a Point
object in this form (p + 6
).
C++ Programming for Experienced Engineers
If you’re looking to sharpen up your C++ programming skills, then you’re in the right place. You will start with learning about dynamic memory allocation, how to create classes, and constructors. In the latter half of the course, inheritance, functions, I/O, exception handling, and more. Throughout the course, you will study over 90 carefully designed examples aimed to enhance your understanding of the C++ language. By the time you finish this course, you will be able to use more advanced functionality in your C++ programs.
A type-cast constructor receives one parameter of any type (other than its own class) to create an object. We define a type-cast constructor in the Point
class to convert an int
into a Point
. In the same way, we can define a type-cast constructor in Point
to convert the object of any other class into Point
.
The use of a type-cast constructor with single-member implementation as a member can work for
Point + Point
andPoint + int
, but not forint + Point
. For implicit invocation of the type-cast constructor for the first operand, the function has to be defined as a non-member.
#include <iostream>using namespace std;class Point {int x, y;public:Point (int a, int b): x(a), y(b) {}Point (int v): x(v), y(v) {}void show() const { cout << "(" << x << "," << y << ") ";}Point operator+ (const Point &rhs) {return Point(x + rhs.x , y + rhs.y);}};int main() {Point p(1,2), q(3,5);p.show();q.show();// The overloaded operator works for both of the followingPoint r = p + q;r.show();Point s = p + 6;s.show();// The overloaded operator cannot work for int + Point// Point t = 7 + p;return 0;}
In the above code:
Line 8: We define another constructor that takes a single integer argument v
. This constructor initializes both x
and y
with the value of v
. This constructor acts as a type-cast constructor and allows for creating a Point
object with a single integer value.
Lines 11–13: We define the operator+
method. This is an overloaded operator method for addition (+
). It takes a single argument, which is a constant reference to another Point
object (rhs
for right-hand side). It returns a new Point
object where the x
coordinate is the sum of x
of the current object and x
of the rhs
object, and the y
coordinate is the sum of y
of the current object and y
of the rhs
object.
Lines 22–23: We use the overloaded +
operator to add the p
and q
objects together, creating a new Point
object r
. Then, we call the show
method for r
to display its coordinates.
Lines 25–26: We use the overloaded +
operator to add an integer value 6
to the p
object, creating a new Point
object s
. The integer value creates a new temporary object with the help of the type-cast constructor and calls the overloaded +
operator receiving two Point
objects. Then, we call the show
method for the resulting object s
to display its coordinates.
Line 29: The code in this line, marked as a comment, attempts to use the overloaded +
operator in a situation where it’s not defined (int + Point
). The +
operator works for adding a Point
object and another Point
object (p + q
) or adding a Point
object and an integer (p + 6
), but it cannot work for adding an integer and a Point
object in this form (7 + p
).
We don’t need to declare a non-member function as friend
if we define getter and setter methods for the relevant attributes.
All of the above versions of overloading an operator in C++ can be implemented as non-member functions. In this case, there are no *this
implicitly available (unlike the member functions) implementations shown in previous sections.
We have to explicitly declare two parameters as per the sequence of operands in the expression used for the operator call. Let’s look at the non-member implementations for three combinations of the same operator.
We use cout
in the overloaded operator functions to understand the calling sequence. However, it is not recommended otherwise.
#include <iostream>using namespace std;class Point {int x, y;public:Point (int a, int b): x(a), y(b) {}void show() const { cout << "(" << x << "," << y << ") " << endl;}int get_x() const {return x;}int get_y() const {return y;}};Point operator+ (const Point &lhs, const Point &rhs) {cout << "P+P "; // The use of cout is not recommended here. This message is only to indicate its call for the reader.return Point(lhs.get_x() + rhs.get_x() , lhs.get_y() + rhs.get_y());}Point operator+ (const Point &lhs, const int &rhs) {cout << "P+i "; // The use of cout is not recommended here. This message is only to indicate its call for the reader.return Point(lhs.get_x() + rhs , lhs.get_y() + rhs);}Point operator+ (const int &lhs, const Point &rhs) {cout << "i+P "; // The use of cout is not recommended here. This message is only to indicate its call for the reader.return Point(lhs + rhs.get_x() , lhs + rhs.get_y());}int main() {Point p(1,2), q(3,5);p.show();q.show();Point r = p + q; // Calls operator+ (Point)r.show();Point s = p + 6; // Calls operator+ (int)s.show();Point t = 7 + p; // Calls operator+ (int, Point)t.show();return 0;}
In the above code, we implement the operator as a non-member function.
Line 8: In this code, we define the show
method with a new line. It is a public member function of the Point
class and is responsible for displaying the current Point
object’s coordinates in the format “(x, y)” followed by a new line.
Lines 9–10: We define the get_x
and get_y
methods to eliminate the need for friend
. They are public member functions of the Point
class and return the values of x
and y
, respectively.
Lines 13–26: We define three overloaded operator+
functions. These functions allow addition operations between Point
objects and integers. The first function (lines 13–16) performs Point + Point
objects, the second (lines 18–21) performs Point + int
, and the third (lines 23–26) performs int + Point
. Each function also adds special messages on the screen: P+P
, P+i
, and i+P
from the first, second, and third implementations, respectively. The result of these additions is a new Point
object with updated coordinates.
Lines 33–34: We use the overloaded +
operator to add the p
and q
objects together, creating a new Point
object r
. This call displays P+P
. Then, we call the show
method for r
to display its coordinates.
Lines 36–37: We use the overloaded +
operator to add an integer value 6
to the p
object, creating a new Point
object s
. This call displays P+i
. Then, we call the show
method for s
to display its coordinates.
Lines 39–40: We use the overloaded +
operator to add the p
object to the integer value 7
, creating a new Point
object t
. This call displays i+P
. Then, we call the show
method for t
to display its coordinates.
Become a C++ Programmer
C++ is a popular language used to develop browsers, games, and operating systems. It's also an essential tool in the development of modern technology like IoT and self-driving cars. This Path will expand your knowledge of C++ with lessons built for professional developers. This Path will take you from basic to advanced concepts with hands-on practice. By the end, you'll have enough C++ experience to confidently solve real-world problems.
When both operands are objects but of two different classes, we should make it a member of the class of the first operand. Since the first operand is the caller, its type should be the same as *this
. However, we can also implement it as a non-member for both classes. Let’s see the complete code for overloading it as two different non-member functions to be called on the basis of the sequence of operands.
#include <iostream>using namespace std;class Point; // It is required by the Dummy classclass Dummy {int d;public:Dummy(int i):d(i){}friend Point operator+ (const Point &lhs, const Dummy &rhs);friend Point operator+ (const Dummy &lhs, const Point &rhs);};class Point {int x, y;public:Point (int a, int b): x(a), y(b) {}void show() const { cout << "(" << x << "," << y << ") ";}friend Point operator+ (const Point &lhs, const Dummy &rhs);friend Point operator+ (const Dummy &lhs, const Point &rhs);};Point operator+ (const Point &lhs, const Dummy &rhs) {return Point(lhs.x + rhs.d , lhs.y + rhs.d);}Point operator+ (const Dummy &lhs, const Point &rhs) {return Point(lhs.d + rhs.x , lhs.d + rhs.y);}int main() {Point p(1,2);Dummy u1(10), u2(20);Point v = p + u1;v.show();Point w = u2 + p;w.show();return 0;}
In the above code:
Line 4: The declaration of the Point
class before the Dummy
class is required for lines 9 and 10.
Lines 5–11: We define another class Dummy
with a private integer data member d
. It has a constructor that initializes d
with the provided integer argument. The purpose of this class is only to demonstrate the addition of two different classes. Practically, it behaves as adding an integer to the Point
object. Since the non-member implementations of the +
operator use the private member d
, both of them are declared as friend
in this class (lines 9–10).
Lines 19–20: We declare both implementations of the +
operator as friend
of class Point
so that they can access the private members x
and y
without being the members of the same class.
Lines 23–29: We define two operator+
functions that allow addition operations between the Point
and Dummy
objects.
Line 33: We create two Dummy
objects, u1
and u2
, and initialize them with values 10
and 20
, respectively.
Line 35: We use the overloaded +
operator to add the Dummy
object u1
to the Point
object p
, creating a new Point
object v
.
Line 37: We use the overloaded +
operator to add the Dummy
object u2
to the Point
object p
, creating a new Point
object w
.
Single non-member implementation of operator overloading can serve the purpose of all three combinations of operator calls. However, it requires a type-cast constructor to be defined in the class. It works by implicitly converting the type of non-class variable to an object. We demonstrate this calling sequence with the help of additional messages display.
Using a type-cast constructor with a single non-member implementation can work for all three combinations of operator calls.
The above diagram explains the involvement of the type-cast constructor in the operator call.
Let’s look at the complete code given below.
We use cout
and show
in the constructors to understand the calling sequence. However, it is not recommended otherwise.
#include <iostream>using namespace std;class Dummy {int d;public:Dummy(int i):d(i){}int get() const {return d;}};class Point {int x, y;public:Point (int a, int b): x(a), y(b) {cout<<" P(x,y)";show();}Point (int v): x(v), y(v) {cout<<" P(i)";show();}Point (const Dummy & obj): x(obj.get()), y(obj.get()) {cout<<" P(D)";show();}void show() const {cout << "(" << x << "," << y << ") ";}int get_x() const {return x;}int get_y() const {return y;}};Point operator+ (const Point &lhs, const Point &rhs) {return Point(lhs.get_x() + rhs.get_x() , lhs.get_y() + rhs.get_y());}int main() {int i = 50;Dummy d = 60;Point p(1,2);cout << endl;Point q = p + d;cout << endl;Point r = p + i;cout << endl;Point s = i + p;cout << endl;Point t = d + p;cout << endl;return 0;}
In the above code:
Lines 4–9: We define the Dummy
class with a private integer data member d
. It has a constructor that initializes d
with the provided integer argument and a member function get
to retrieve the value of d
. This new method eliminates the need for a friend
declaration.
Lines 11–31: We define the Point
class with private integer data members x
and y
. It has multiple constructors: One that takes two integers (line 14), another that takes a single integer (line 18), and one that takes a Dummy
object (line 22). The constructors initialize the Point
object’s coordinates and display a message indicating the type of constructor used. The class also has member functions show
, get_x
, and get_y
to display both coordinates, to retrieve the value of the x coordinate, and to retrieve the value of the y coordinate, respectively.
The use of getter methods,
get_x
andget_y
, eliminates the need for afriend
declaration. It is a safer way of implementing through a non-member function.
Lines 33–35: We overload the +
operator for adding Point
objects. It takes two Point
objects as parameters and returns a new Point
object with coordinates being the sum of corresponding coordinates of the two input Point
objects.
Inside int main()
:
Line 38: We declare an integer variable i
and initialize it with the value 50
.
Line 39: We declare a Dummy
object d
and initialize it with the value 60
.
Lines 41–42: We create a Point
object p
using the constructor that takes two integers (1
and 2
) and displays them from the parameterized constructor (line 14). It outputs P(x,y)
to indicate a call to the constructor. We print a new line afterward.
Line 44: We use the overloaded +
operator to perform Point + Dummy
through p + d
. We display the resulting Point
object q
from the constructor used for q
. The P(D)
in the output indicates that the type-cast constructor for Dummy
to Point
conversion is called.
Line 47: The overloaded +
operator is used to perform Point + int
through p + i
. We display the resulting Point
object r
from the constructor used for r
. The P(i)
in the output indicates that the type-cast constructor for int
to Point
conversion is called.
Line 50: We use the overloaded +
operator to perform int + Point
through i + p
. We display the resulting Point
object s
from the constructor used for s
. The P(i)
in the output indicates that the type-cast constructor for int
to Point
conversion is called.
Line 53: We use the overloaded +
operator to perform Dummy + Point
through d + p
. We display the resulting Point
object t
from the constructor used for t
. The P(D)
in the output indicates that the type-cast constructor for Dummy
to Point
conversion is called.
Zero to Hero in C++
C++ is a robust and flexible language commonly used for games, desktop, and embedded applications development. This Skill Path is perfect for beginners eager to learn C++ and embark on a programming journey. You’ll explore C++ fundamentals, starting with basic syntax and functionality to create programs, and then dive into more complex concepts like dynamic memory allocation in C++. The latter half focuses on C++ programming with a detailed overview of object-oriented programming (OOP), which includes classes in C++, data hiding in C++, encapsulation in C++, abstraction in C++, inheritance in C++, and polymorphism in C++. Hands-on practice with algorithms and data structures will empower you to write real-world programs confidently, paving your way as a C++ developer.
Operators can be overloaded as non-members and members of the class. It depends on the caller object whether we can define an operator as a class member or not. If the caller object is not an object of the class, we cannot define it as a member function; otherwise, we can implement it in both ways. If we overload an operator as a non-member for both operands to be the objects of the class, then providing the type-cast constructor in the class can empower that operator to work for all combinations of operator calls.
Some operators cannot be overloaded as non-members, e.g., subscript and function call operators.
Keep exploring, keep coding, and happy learning!
To start learning these concepts and more, check out Educative’s Data Structures Preliminaries (Refresher of Fundamentals in C++) course.
Free Resources