Home/Blog/Programming/Operator overloading in C++
Home/Blog/Programming/Operator overloading in C++

Operator overloading in C++

16 min read

Become a Software Engineer in Months, Not Years

From your first line of code, to your first day on the job — Educative has you covered. Join 2M+ developers learning in-demand programming skills.

Operator overloading is useful for defining user-defined functionality for built-in operators. The familiarity of the symbols and their judicious new definition adds to the convenience of reading and writing expressions. The following programming languages are included in the list of providers of this facility: Ada, C++, C#, Python, Ruby, Swift, and Kotlin. We use the C++ language for coding examples in this blog.

Let’s dive right in!

We’ll cover:


Introduction#

Operator overloading is the power of a programming language that allows the built-in operators (++, -, *, etc.) to be overloaded for user-defined data types. The familiarity of the symbols for an expected behavior facilitates reading and writing. The cascading of multiple function calls is easy to understand in expressions.

Operator overloading is a powerful tool for expressing complicated invocations concisely.

One of the arguments against the facility of operator overloading is the possibility of irrelevant or inconsistent definitions. It is important that the developers defining the new behavior for the operators should keep in mind the general expectation of their usage. The overloaded version of the ++ operator should not do any additional or irrelevant operations under the hood.

The new definition of familiar symbols should be judiciously created to avoid confusion.

For example, we perform a+ba + b on the objects/variables of the polynomial class. The overloaded operator, ++ for this class, should sum up two polynomials without changing the operands, as expected by the definition of this operation in mathematics.

In all the coding examples, the term 5x25x^2 is output as 5x25x2, where 55 is the coefficient, and 22 is the exponent of the variable xx.

Zero to Hero in C++

Cover
Become a C++ Programmer

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.

38hrs
Beginner
32 Challenges
46 Quizzes


Method vs. operator#

An object has attributes (also called the data members of the class) and methods (also called the member functions of the class). Functions and methods can be overloaded for the following reasons.

  1. Different types of parameters
  2. Different order of parameters
  3. Different number of parameters

However, the operators cannot be overloaded for the third reason mentioned above. The number of parameters for the operators cannot be changed. It remains the same as defined by the language for primitive data types. A binary operator cannot be defined for less than or greater than two operands. Similarly, a unary operator cannot be defined for less than or greater than one operand. When we define a binary operator as a class method, we can use only one explicit parameter (neither less nor more) for the second operand. The first operand implicitly comes as the calling object.

Difference between methods/functions and operators
Difference between methods/functions and operators

The operators are overloaded as methods. In C++, the operator keyword is used to overload an operator, and the symbol has to be from the permissible ones. Many operators in C++ can be overloaded.

The method can have any name following the rules of the language. Calling an operator is also a bit different from the method.


Difference of invocation#

A method of an object is called using the member selection operator, ., between the object name and the method name. The method parameters are passed inside the parentheses after the method name. Calling an operator does not require the use of a member selection operator and parentheses. The following simple implementation of class Polynomial is used to demonstrate this difference.

// header file for cout and endl
#include <iostream>
// header file for abs()
#include <cstdlib>
// header file for vector<int>
#include <vector>
using namespace std;
class Polynomial {
vector<int> coef;
public:
Polynomial(const vector<int> & coefficients) : coef(coefficients) {}
// Function to display a term of the polynomial
void showTerm(int val) const {
if (val != 0) {
if (val > 0) {
cout << " + ";
} else {
cout << " - ";
}
cout << abs(val);
}
}
// Function to display the polynomial
void show() const {
int lim = coef.size() - 1;
for (int i = lim; i >= 0; --i) {
// Showing the coefficient with the sign
showTerm(coef[i]);
// Showing the variable and exponent
cout << "x" << i;
}
cout << endl;
}
// Overloading the + operator to add two polynomials and return the result
Polynomial operator+ (const Polynomial &other) const {
Polynomial result = *this;
for (size_t i = 0; i < other.coef.size(); ++i) {
if (i < result.coef.size()) {
result.coef[i] += other.coef[i];
} else {
result.coef.push_back(other.coef[i]);
}
}
return result;
}
// Function to add two polynomials and return the result
Polynomial plus(const Polynomial &other) const {
Polynomial result = *this;
for (size_t i = 0; i < other.coef.size(); ++i) {
if (i < result.coef.size()) {
result.coef[i] += other.coef[i];
} else {
result.coef.push_back(other.coef[i]);
}
}
return result;
}
};
int main() {
vector<int> va = {-1, -2, -3};
vector<int> vb = {10, 20, 30};
vector<int> vc = {3, -4, 5};
Polynomial a = va;
Polynomial b = vb;
Polynomial c = vc;
// Notice the two cascaded calls in the RHS of both of the following lines:
// a is the caller and b is the parameter in the first call
// The result of the first call is caller and c is the parameter in the second call
Polynomial r = a + b + c; // No use of dot and parentheses for +
Polynomial s = a.plus(b).plus(c); // Use of dot and parentheses for plus
// Showing the values of all objects by calling the show method using dot and parentheses.
a.show();
b.show();
c.show();
r.show();
s.show();
return 0;
}

In the above code:

  • Lines 10–63: We define class Polynomial as having one data member, one type-cast constructor, and four methods. The plus() method and the overloaded operator + have the same behavior. They are included to demonstrate the difference between the calling of these two methods.

  • Lines 16–25: We define the showTerm() method. It is a public member function that takes a coefficient as a parameter and displays it along with the appropriate sign. It ensures that positive coefficients are displayed with a "+" sign and negative coefficients are displayed with a "-" sign. This separation of concerns makes the code more modular and easier to understand.

  • Lines 27–36: We define the show() method that displays the polynomial by iterating through the coefficients. It calls showTerm() to display the coefficient of each term.

  • Lines 39–49: We overload the addition operator using the function operator+. The function takes a constant reference to another Polynomial object as a parameter and returns a new Polynomial object representing the sum of the two polynomials. Inside the function, the + operator is applied element-wise to the coefficients of the polynomials. Notice the use of *this in line 40 to initialize the result with the values of the calling object (the first operand). Returning the object of class type (line 48) enables the cascaded calls.

  • Lines 52–62: We define the plus() method, which performs the same addition operation as the operator+ function. This method allows the addition of two polynomials and returns the result as a new Polynomial object. We copy the values of the calling object to result in line 53. Returning the object of class type (line 61) enables the cascaded calls.

In main():

  • Lines 66–71: We create three objects of Polynomial: a, b, and c, using vectors va, vb, and vc, respectively.

The following two lines demonstrate the difference between calling an overloaded operator vs. calling a method.

  • Lines 76: We demonstrate the call to operator+ without using dot and parenthesis. We also show two cascaded calls. The first call is a + b, and the second is result + c. The caller of the first call is a, and the second is the result of a + b.

  • Line 77: We demonstrate the call to plus() with the help of dot and parenthesis. We also show the cascaded calls of this method. The caller of the first call is a, and the second is the resulting object returned by a.plus(b).

At the end:

  • Lines 80–84: We call the show() method for objects a, b, c, r, and s using dot notation and parentheses, demonstrating the use of methods to display polynomial values. Notice that the values of r and s are the same.


The operators that can be overloaded#

The following are various types of operators that can be overloaded in C++.

Various types of operators in C++
Various types of operators in C++

Arithmetic operators: All arithmetic operators can be overloaded: +, -, *, /and %. A popular example is the overloaded operator + for strings.

Bitwise operators: All bitwise operators can be overloaded: ^, |, &, ~, <<, and >>. The popular examples are the use of operators << and >> for output and input.

Assignment and compound assignment operators: All assignment operators can be overloaded: =, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, and >>=. It is important to note that the assignment operator (=) must be overloaded as a member function of the class. This operator is as necessary as providing a copy-constructor in the class. Usually, when we use pointer data members in a class, we provide these two functionalities to avoid buggy results due to the default member-wise copy and assignment.

Relational operators: All relational operators can be overloaded: ==, !=, <, >, <=, and >=. Usually, only < is overloaded in detail, and all others are defined in terms of this operator. It saves the maintenance effort in the future.

Logical operators: All logical operators can be overloaded: !, &&, and ||. A popular example is the overloaded operator ! to test the validity of i/o streams.

Increment and decrement operators: All increment and decrement operators can be overloaded: ++ and --. The pre-increment and pre-decrement operators are implemented as unary operators, while post-increment and post-decrement are implemented as binary operators. The second operand in the case of post-increment/post-decrement is the value 1 sent by the language as an int type.

Subscript operator: The subscript operator [] can be overloaded as a member of the class. It has two possible implementations for a class: RValue and LValue. In the presence of the LValue version, the RValue can be provided only for const objects. The LValue version returns a reference type. Both versions can have only one parameter of any type. A popular example is the overloaded subscript operator for maps/dictionaries.

Function call operator: The function operator () can be overloaded as a member of the class. It can have any number of parameters and have several overloaded versions in a class.

Miscellaneous operators: The following operators can also be overloaded in C++: address (&), reference (&), pointer indirection (*), member reference operator through pointer (->), memory management operators (new and delete), type conversion operators (()), and the comma operator (,).

Data Structures Preliminaries (Refresher of Fundamentals in C++)

Cover
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++.

30hrs
Beginner
151 Playgrounds
3 Quizzes


The operators that cannot be overloaded#

Most of the operators in C++ can be overloaded, except the following:

Operator Name Operator Token
Conditional ?:
Member selection .
Member pointer indirection .*
Scope resolution ::
Object size information sizeof
Object type information typeid
Static casting operator static_cast
Const casting operator const_cast
Raw casting operator reinterpret_cast
Polymorphic casting operator dynamic_cast


Overloading binary operators#

A binary operator has two operands. The above example illustrates the overloading of a binary operator +. The language definition specifies which operators are binary in that language. Most of the operators that can be overloaded in C++ are binary, including arithmetic, relational, logical, bit-wise, and assignment.


The role of the first operand#

If the first operand of a binary operator is an object of our class, then we can overload it as a member function of the class. The second operand of a binary operator is received as a parameter in the overloaded version when the operator is overloaded as a member of the class. Every non-static member function (method or operator) implicitly receives the caller object as its first argument. It is accessible through the keyword this, which is a pointer of the class type. In some cases, we need to use the this pointer, but usually we don’t need to explicitly use it.

The following code demonstrates the use of the first operand as an object of the class. We declare the operator const because we don’t want to change any data in the first operand. It adds to the safety and is followed as a best practice.

We explicitly write a call to show() using this inside the overloaded operator only to demonstrate its values.

#include <iostream>
#include <cstdlib>
#include <vector>
using namespace std;
class Polynomial {
vector<int> coef;
public:
Polynomial(const vector<int> & coefficients) : coef(coefficients) {}
void showTerm(int val) const {
if (val != 0) {
if (val > 0) {
cout << " + ";
} else {
cout << " - ";
}
cout << abs(val);
}
}
void show() const {
int lim = coef.size() - 1;
for (int i = lim; i >= 0; --i) {
// Showing the coefficient with the sign
showTerm(coef[i]);
// Showing the variable and exponent
cout << "x" << i;
}
cout << endl;
}
// Overloading the + operator to add two polynomials and return the result
Polynomial operator+ (const Polynomial &other) const {
cout << "The code of operator+ starts here.\n";
// Showing the first operand being the caller object
cout << " The first operand is the caller:\n "; this->show();
// Showing the second operand
cout << " The second operand is the parameter:\n "; other.show();
Polynomial result = *this;
for (size_t i = 0; i < other.coef.size(); ++i) {
if (i < result.coef.size()) {
result.coef[i] += other.coef[i];
} else {
result.coef.push_back(other.coef[i]);
}
}
cout << "The code of operator+ ends here.\n";
return result;
}
};
int main() {
vector<int> va = {-1, -2, -3};
vector<int> vb = {10, 20, 30};
Polynomial a = va;
Polynomial b = vb;
Polynomial c = a + b; // a is the caller and b is the parameter
// Showing the resulting object.
cout << "\nThe resulting object is:\n"; c.show();
return 0;
}

Let’s focus on the overloaded operator in the above code:

  • Lines 35–51: The operator+() is the overloaded operator that adds two Polynomial objects. It displays a message indicating the start of the operator overloading process in line 36. Then, it shows the operands (the caller object *this and the parameter other) in lines 38 and 40. It then performs the addition of coefficients. Then, it displays a message indicating the end of the operator overloading process in line 49.

  • Line 62: Inside the main() function, we display the resulting Polynomial object c using the show() method.


Overloading as a friend of the class#

We can also overload the same operator without making it the member function of the class. In this case, we need to declare such non-member functions as a friend of the class so that they can access the private data of that class.

If the first operand of a binary operator is not an object of the class, then the operator must be overloaded as a non-member.

The first operand should be received by value or as a constant reference when we don’t want to change it (as in the case of the + operator). It adds to the safety of accidental writes inside the function definition. The following code demonstrates the same.

#include <iostream>
#include <cstdlib>
#include <vector>
using namespace std;
class Polynomial {
vector<int> coef;
public:
Polynomial(const vector<int> & coefficients) : coef(coefficients) {}
void showTerm(int val) const {
if (val != 0) {
if (val > 0) {
cout << " + ";
} else {
cout << " - ";
}
cout << abs(val);
}
}
void show() const {
int lim = coef.size() - 1;
for (int i = lim; i >= 0; --i) {
// Showing the coefficient with the sign
showTerm(coef[i]);
// Showing the variable and exponent
cout << "x" << i;
}
cout << endl;
}
friend Polynomial operator+ (const Polynomial &first, const Polynomial &other);
};
// Overloading the + operator to add two polynomials and return the result
Polynomial operator+ (const Polynomial &first, const Polynomial &other) {
cout << "The code of FRIEND operator+ starts here.\n";
// Showing the first operand being the caller object
cout << " The first operand is the first parameter:\n "; first.show();
// Showing the second operand
cout << " The second operand is the second parameter:\n "; other.show();
Polynomial result = first;
for (size_t i = 0; i < other.coef.size(); ++i) {
if (i < result.coef.size()) {
result.coef[i] += other.coef[i];
} else {
result.coef.push_back(other.coef[i]);
}
}
cout << "The code of FRIEND operator+ ends here.\n";
return result;
}
int main() {
vector<int> va = {-1, -2, -3};
vector<int> vb = {10, 20, 30};
Polynomial a = va;
Polynomial b = vb;
Polynomial c = a + b; // a is the caller and b is the parameter
// Showing the resulting object.
cout << "\nThe resulting object is:\n"; c.show();
return 0;
}

In the above code, let’s focus only on the friend function and its details:

  • Line 34: We declare the operator+() function as a friend of the Polynomial class. This allows the operator+() function to access the private members of the Polynomial class.
  • Lines 37–53: We define the operator+() function outside of the class. It takes two Polynomial objects as parameters and overloads the + operator. Inside the function:
    • It displays a message indicating the start of the friend operator overloading process in line 38.
    • Then, it shows the operands (the parameters first and other) in lines 40 and 42.
    • It then performs the addition of coefficients.
    • Then, it displays a message indicating the end of the friend operator overloading process in line 51.

Using the power of friend, we can also overload a binary operator whose first operand is not an object of our class.

In C++, the private members of a class can be accessed from the member functions (of the same class) or the friend functions.

Become a C++ Programmer

Cover
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.

119hrs
Beginner
82 Challenges
152 Quizzes


Overloading as a non-member and non-friend#

We don’t need to declare such non-member functions as friends if they do not access the private members of the class directly. The use of friend provides a way to intrude into the private area of the class without validity and stability testing.

The use of friend is a breach of encapsulation.

If we have properly encapsulated the private members of the class through a public interface, then we don’t need to access the private members directly. The following code demonstrates the same.

#include <iostream>
#include <cstdlib>
#include <vector>
using namespace std;
class Polynomial {
vector<int> coef;
public:
Polynomial(const vector<int> & coefficients) : coef(coefficients) {}
size_t degree() const {
return coef.size();
}
int getTerm(int ind) const {
if (ind >= 0 && ind < coef.size()) {
return coef[ind];
}
return 0;
}
void setTerm(int ind, int val) {
if (ind >= 0 && ind < coef.size()) {
coef[ind] = val;
}
}
void newTerm(int val) {
coef.push_back(val);
}
void showTerm(int val) const {
if (val != 0) {
if (val > 0) {
cout << " + ";
} else {
cout << " - ";
}
cout << abs(val);
}
}
void show() const {
int lim = coef.size() - 1;
for (int i = lim; i >= 0; --i) {
// Showing the coefficient with the sign
showTerm(coef[i]);
// Showing the variable and exponent
cout << "x" << i;
}
cout << endl;
}
};
// Overloading + operator to add two polynomials and return the result
// as a non-member and non-friend, through public methods in the class
Polynomial operator+ (const Polynomial &first, const Polynomial &other) {
Polynomial result = first;
// Using public method degree() instead of accessing private coef.size()
for (size_t i = 0; i < other.degree(); ++i) {
if (i < result.degree()) {
// Using public method getTerm(i) instead of accessing private coef[i]
int newVal = result.getTerm(i) + other.getTerm(i);
// Using public method setTerm(i,newVal) instead of coef[i] = newVal
result.setTerm(i,newVal);
} else {
// Using public method newTerm(i) instead of coef.push_back()
result.newTerm(other.getTerm(i));
}
}
return result;
}
int main() {
vector<int> va = {-1, -2, -3};
vector<int> vb = {10, 20, 30};
Polynomial a = va;
Polynomial b = vb;
Polynomial c = a + b; // a is the caller and b is the parameter
// Showing the resulting object.
cout << "\nThe resulting object is:\n";
c.show();
return 0;
}

In the above code, let’s focus on the operator overloaded as non-member and non-friend:

  • Lines 12–14: We define the degree() method. It is a public member function of the Polynomial class that returns the size of the coefficient vector as the degree of the polynomial.
  • Lines 16–21: We define a public member function that getTerm() takes an index ind as a parameter and returns the coefficient at that index. If the index is out of range, it returns 0 to indicate the non-existence of the term in the polynomial.
  • Lines 23–27: We define the setTerm() method. It is a public member function that takes an index ind and a value val as parameters and sets the coefficient at the given index to the provided value. If the index is out of range, it does nothing.
  • Lines 29–31: We define the newTerm() public method. It adds a new term (coefficient) to the polynomial by pushing the val value to the end of the coefficient vector.
  • Lines 55–72: We define operator+() as a function outside the class. It is an overloaded addition operator that takes two Polynomial objects (first and other) as parameters. Inside the function, it utilizes the public methods degree(), getTerm(), setTerm(), and newTerm() to perform the addition of two polynomials. It creates a new Polynomial object result and returns it.


The role of the second operand#

The second operand of a binary operator is received as a parameter in the overloaded version when the operator is overloaded as a member of the class. When a binary operator is overloaded as a non-member function, then the second operand is received as the second parameter of the class. The second operand should be received by value or as a constant reference. It adds to the safety of accidental writes inside the function definition.

C++ Programming for Experienced Engineers

Cover
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.

11hrs
Intermediate
12 Challenges
2 Quizzes


Overloading unary operators#

A unary operator is one that has only one operand, which is considered the caller of the operator. The language definition specifies which operators are unary in that language. The following unary operators can be overloaded in C++: -, ~, !, ++, and --. The following operators (listed under the miscellaneous operators above) are also unary: address of (&), reference (&), pointer indirection (*), memory management (new and delete), and type conversion operators.

The name of the type conversion operators works as their return type. There should be no return type before the operator keyword in this case.

We can overload unary operators as member functions of the class. The operand is the caller object accessible through the this keyword. The following code demonstrates the overloading of a unary operator as a member function. We declare it as a const member function because we don’t want to change the caller object in it.

We explicitly write a call to show using this inside the overloaded operator just to show the value of the caller object.

#include <iostream>
#include <cstdlib>
#include <vector>
using namespace std;
class Polynomial {
vector<int> coef;
public:
Polynomial(const vector<int> & coefficients) : coef(coefficients) {}
void showTerm(int val) const {
if (val != 0) {
if (val > 0) {
cout << " + ";
} else {
cout << " - ";
}
cout << abs(val);
}
}
void show() const {
int lim = coef.size() - 1;
for (int i = lim; i >= 0; --i) {
// Showing the coefficient with the sign
showTerm(coef[i]);
// Showing the variable and exponent
cout << "x" << i;
}
cout << endl;
}
// Overloading the - operator to return a polynomial with inverted signs of the coefficients of the original
Polynomial operator- () const {
Polynomial result = *this;
for (size_t i = 0; i < result.coef.size(); ++i) {
result.coef[i] = -result.coef[i];
}
return result;
}
};
int main() {
vector<int> va = {1, -2, -3};
Polynomial a = va;
Polynomial b = -a; // Use of unary negation
// Showing the values of all objects by calling the method show
a.show();
b.show();
return 0;
}

In the above code, let’s focus on the definition and use of the overloaded unary operator:

  • Lines 34–41: We overload the unary negation operator-() for the Polynomial class. The operator-() returns a new Polynomial object with the coefficients with inverted signs. The *this pointer is used to access the operand (caller object), and a new Polynomial object result is initialized with the caller object. The coefficients of result are then inverted by negating each coefficient in the loop.
  • Lines 44–52: Inside the main() function, a vector va is used to create a Polynomial object a. The unary negation operator is applied to a in line 47, and a new Polynomial object b is created with inverted coefficients resulting from the operator call. The show() method is called for objects a and b, demonstrating the use of the overloaded unary negation operator.

Note that there is no parameter when we overload a unary operator as a member function of the class. The only operand of a unary operator is received in *this being the caller object of this operator.


Unary operator as a friend of the class#

We can overload the same operator without making it the member function of the class, declaring it a friend of the class to access the private data directly. The operand should be received by value or as a constant reference when we don’t want to change it. It adds to the safety. The following code demonstrates the same.

#include <iostream>
#include <cstdlib>
#include <vector>
using namespace std;
class Polynomial {
vector<int> coef;
public:
Polynomial(const vector<int> & coefficients) : coef(coefficients) {}
void showTerm(int val) const {
if (val != 0) {
if (val > 0) {
cout << " + ";
} else {
cout << " - ";
}
cout << abs(val);
}
}
void show() const {
int lim = coef.size() - 1;
for (int i = lim; i >= 0; --i) {
// Showing the coefficient with the sign
showTerm(coef[i]);
// Showing the variable and exponent
cout << "x" << i;
}
cout << endl;
}
friend Polynomial operator- (const Polynomial &one);
};
// Overloading - operator to return a polynomial with inverted signs of the coefficients of the original
Polynomial operator- (const Polynomial &one) {
Polynomial result = one;
for (size_t i = 0; i < result.coef.size(); ++i) {
result.coef[i] = -result.coef[i];
}
return result;
}
int main() {
vector<int> va = {1, -2, -3};
Polynomial a = va;
Polynomial b = -a; // Use of unary minus
// Showing the values of all objects by calling the method show
a.show();
b.show();
return 0;
}

In the above code, let’s focus only on the friend function and its details:

  • Line 34: We declare the operator-() function as a friend of the Polynomial class. This allows the operator-() function to access the private members of the Polynomial class.
  • Lines 37–44: We define the operator-() function outside of the class. It takes a Polynomial object as a parameter and overloads the - operator. Inside the function, it performs the negation of coefficients of the parameters and stores them to the coefficients of another object result.

The logic of not making a friend for binary operators remains the same for unary operators. We don’t need to declare such non-member functions as friends if they do not access the class’s private members directly. If we properly encapsulate the class’s private members through public methods, we don’t need to access the private members directly. In this case, we need to provide the public methods degree(), getTerm(), and setTerm() to perform the negation of a polynomial.


Wrapping up and next steps#

The overloading of operators is a powerful tool provided by C++ to mimic the abstract data types (classes) that behave more like primitive data types. Certain operators cannot be overloaded, while the majority of operators are allowed to be overloaded. Some operators must be made the member of the class if there is a need to overload them. All other operators can be overloaded as member functions and as non-members. If the caller (the first operand) of an operator is not a class object, then the operator cannot be overloaded as a member of that class.

Happy learning!


To start learning these concepts and more, check out Educative’s Data Structures Preliminaries (Refresher of Fundamentals in C++) course.

Continue learning to code#


 
Join 2.5 million developers at
Explore the catalog

Free Resources