Various ways of overloading an operator in C++
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:
Introduction#
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.
Overloading based on calling#
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.
Class and class#
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.
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 thePointclass. Theoperator+function takes a constant reference to anotherPointobject (rhs) and returns a newPointobject whosexcoordinate is the sum of thexcoordinates of the two points, and theycoordinate is the sum of theycoordinates of the two points. -
Lines 21–22: We use the overloaded
+operator to add pointspandq, creating a newPointobjectr. The coordinates ofrare (1 + 3, 2 + 5) = (4, 7). The result is displayed using theshowmember function. -
Lines 25–26: These lines are commented out to demonstrate that the overloaded
+operator does not work for adding aPointobject and an integer, or an integer and aPointobject, 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++.
Class and integer#
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.
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 (rhsfor the right-hand side). It returns a newPointobject where thexandycoordinates are increased by the value ofrhs. -
Lines 20–21: We use the overloaded
+operator to add the integer value6to thepobject, creating a newPointobjects. Then, we call theshowmethod forsto 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 aPointobject (p + 6), but it cannot work for adding twoPointobjects together (p + q) or adding aPointobject to an integer (7 + p).
Integer and class#
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.
In the above code:
-
Line 10: We declare a friend function
operator+inside thePointclass. This is an overloaded operator method for addition (+). It takes an integer (lhsfor the left-hand side) and a constant reference to aPointobject (rhsfor the right-hand side) as arguments. Declaring it as a friend function allows it to access the private members of thePointclass. -
Lines 13–15: We define the
operator+function outside the class. It takes an integerlhsand a constant reference to aPointobjectrhs. Inside the function, it creates and returns a newPointobject where thexcoordinate is the sum oflhsandrhs.x, and theycoordinate is the sum oflhsandrhs.y. -
Lines 22–23: We use the overloaded
+operator to add the integer value7to thepobject, creating a newPointobjectt. Then, we call theshowmethod fortto 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 aPointobject (7 + p), but it cannot work for adding twoPointobjects together (p + q) or adding an integer to aPointobject 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.
The power of the type-cast constructor#
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 + PointandPoint + 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.
In the above code:
-
Line 8: We define another constructor that takes a single integer argument
v. This constructor initializes bothxandywith the value ofv. This constructor acts as a type-cast constructor and allows for creating aPointobject 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 anotherPointobject (rhsfor right-hand side). It returns a newPointobject where thexcoordinate is the sum ofxof the current object andxof therhsobject, and theycoordinate is the sum ofyof the current object andyof therhsobject. -
Lines 22–23: We use the overloaded
+operator to add thepandqobjects together, creating a newPointobjectr. Then, we call theshowmethod forrto display its coordinates. -
Lines 25–26: We use the overloaded
+operator to add an integer value6to thepobject, creating a newPointobjects. The integer value creates a new temporary object with the help of the type-cast constructor and calls the overloaded+operator receiving twoPointobjects. Then, we call theshowmethod for the resulting objectsto 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 aPointobject and anotherPointobject (p + q) or adding aPointobject and an integer (p + 6), but it cannot work for adding an integer and aPointobject 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.
Overloading as a non-member#
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.
In the above code, we implement the operator as a non-member function.
-
Line 8: In this code, we define the
showmethod with a new line. It is a public member function of thePointclass and is responsible for displaying the currentPointobject’s coordinates in the format “(x, y)” followed by a new line. -
Lines 9–10: We define the
get_xandget_ymethods to eliminate the need forfriend. They are public member functions of thePointclass and return the values ofxandy, respectively. -
Lines 13–26: We define three overloaded
operator+functions. These functions allow addition operations betweenPointobjects and integers. The first function (lines 13–16) performsPoint + Pointobjects, the second (lines 18–21) performsPoint + int, and the third (lines 23–26) performsint + Point. Each function also adds special messages on the screen:P+P,P+i, andi+Pfrom the first, second, and third implementations, respectively. The result of these additions is a newPointobject with updated coordinates. -
Lines 33–34: We use the overloaded
+operator to add thepandqobjects together, creating a newPointobjectr. This call displaysP+P. Then, we call theshowmethod forrto display its coordinates. -
Lines 36–37: We use the overloaded
+operator to add an integer value6to thepobject, creating a newPointobjects. This call displaysP+i. Then, we call theshowmethod forsto display its coordinates. -
Lines 39–40: We use the overloaded
+operator to add thepobject to the integer value7, creating a newPointobjectt. This call displaysi+P. Then, we call theshowmethod fortto 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.
Two distinct classes#
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.
In the above code:
-
Line 4: The declaration of the
Pointclass before theDummyclass is required for lines 9 and 10. -
Lines 5–11: We define another class
Dummywith a private integer data memberd. It has a constructor that initializesdwith 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 thePointobject. Since the non-member implementations of the+operator use the private memberd, both of them are declared asfriendin this class (lines 9–10). -
Lines 19–20: We declare both implementations of the
+operator asfriendof classPointso that they can access the private membersxandywithout being the members of the same class. -
Lines 23–29: We define two
operator+functions that allow addition operations between thePointandDummyobjects. -
Line 33: We create two
Dummyobjects,u1andu2, and initialize them with values10and20, respectively. -
Line 35: We use the overloaded
+operator to add theDummyobjectu1to thePointobjectp, creating a newPointobjectv. -
Line 37: We use the overloaded
+operator to add theDummyobjectu2to thePointobjectp, creating a newPointobjectw.
One overload for all calls#
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.
In the above code:
-
Lines 4–9: We define the
Dummyclass with a private integer data memberd. It has a constructor that initializesdwith the provided integer argument and a member functiongetto retrieve the value ofd. This new method eliminates the need for afrienddeclaration. -
Lines 11–31: We define the
Pointclass with private integer data membersxandy. It has multiple constructors: One that takes two integers (line 14), another that takes a single integer (line 18), and one that takes aDummyobject (line 22). The constructors initialize thePointobject’s coordinates and display a message indicating the type of constructor used. The class also has member functionsshow,get_x, andget_yto 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_xandget_y, eliminates the need for afrienddeclaration. It is a safer way of implementing through a non-member function. -
Lines 33–35: We overload the
+operator for addingPointobjects. It takes twoPointobjects as parameters and returns a newPointobject with coordinates being the sum of corresponding coordinates of the two inputPointobjects.
Inside int main():
-
Line 38: We declare an integer variable
iand initialize it with the value50. -
Line 39: We declare a
Dummyobjectdand initialize it with the value60. -
Lines 41–42: We create a
Pointobjectpusing the constructor that takes two integers (1and2) and displays them from the parameterized constructor (line 14). It outputsP(x,y)to indicate a call to the constructor. We print a new line afterward. -
Line 44: We use the overloaded
+operator to performPoint + Dummythroughp + d. We display the resultingPointobjectqfrom the constructor used forq. TheP(D)in the output indicates that the type-cast constructor forDummytoPointconversion is called. -
Line 47: The overloaded
+operator is used to performPoint + intthroughp + i. We display the resultingPointobjectrfrom the constructor used forr. TheP(i)in the output indicates that the type-cast constructor forinttoPointconversion is called. -
Line 50: We use the overloaded
+operator to performint + Pointthroughi + p. We display the resultingPointobjectsfrom the constructor used fors. TheP(i)in the output indicates that the type-cast constructor forinttoPointconversion is called. -
Line 53: We use the overloaded
+operator to performDummy + Pointthroughd + p. We display the resultingPointobjecttfrom the constructor used fort. TheP(D)in the output indicates that the type-cast constructor forDummytoPointconversion 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.
Wrapping up and next steps#
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.