Introduction to Operator Overloading
Operator overloading is one of the best features of C++. By overloading the operators, we can give additional meaning to the operators like +-*/=.,= etc., which by default are supposed to work only on standard data types like int, float, char, void etc. It is an essential concept in C++. It’s a type of polymorphism in which an operator is overloaded to give it the user-defined meaning.
C++ allows us to specify more than one definition for a function name or an operator in the same scope, which is called function overloading and operator overloading, respectively. The process of selecting the most suitable overloaded function or operator is called overload resolution.
So now let’s understand what is operator overloading in c++.
What is operator overloading in C++?
Operator overloading in c++ is defined as one of the best features that is used to overload most of the operators like “+” “–” “*” “/” “=” “.” “,” etc in c++.
Table of contents:
What are Operators?
An operator is a symbol that tells the compiler to perform specific mathematical, logical calculations or some other special operations.
What are the types of operator overloading?
There are two types of operator overloading:
- Function overloading.
- Operator overloading.
![Types of Operator Overloading](https://d1m75rqqgidzqn.cloudfront.net/wp-data/2022/09/15093900/image-6.png)
What is function overloading?
The process of having two or more functions with the same name but with different parameters (arguments) is called function overloading. The function is redefined by either using different types of arguments or a different number of arguments. It is only through these differences that a compiler can differentiate between functions.
What is Operator overloading?
In C++, it can add special features to the functionality and behaviour of already existing operators like athematic and other operations. The mechanism of giving special meaning to an operator is known as operator overloading. For example, we can overload an operator ‘+’ in a class-like string to concatenate two strings by just using +.
Operations that can be performed:
- Athematic operations: + – * / %
- Logical operations: && and ||
- Relational operations: == != >= <=
- Pointer operators: & and *
- Memory management operator: new, delete []
Implementing Operator overloading:
- Member function: It is in the scope of the class in which it is declared.
- Friend function: It is a non-member function of a class with permission to access both private and protected members.
Operator Overloading Examples
Example 1: Let us multiply two fractions using the overloading of the multiplication operator in C++.
// Multiplication of two fractions
#include <iostream>
using namespace std; class Frac { private: int a; int b; public: Frac() : a(0), b(0) {} void in() { cout << "Enter the numerator : "; cin >> a; cout<< "Enter the denominator : "; cin >> b; } // Overload the * operator Frac operator * (const Frac &obj) { Frac temp; temp.a = a * obj.a; temp.b = b * obj.b; return temp; } void out() { cout<<"The fraction is "<< a<<"/ "<<b; }
}; int main() { Frac F1, F2, result; cout << "Enter the first fraction:\n"; F1.in(); cout << "Enter the second fraction:\n"; F2.in(); // complex1 calls the operator function // complex2 is passed as an argument to the function result = F1 * F2; result.out(); return 0;
}
OutPut
Enter the first fraction:
Enter the numerator : 2
Enter the denominator : 5 Enter the second fraction:
ENter the numerator: 12
Enter the denominator: 7
The fraction is 24/35
Example 2: A C++ program to overload a prefix decrement operator
#include <iostream>
using namespace std; class OverLoad { private: int a; int b; public: OverLoad() : a(0), b(0) {} void in() { cout << "Enter the first number : "; cin >> a; cout<< "Enter the second number : "; cin >> b; } // Overload the prefix decrement operator void operator-- () { a= --a; b= --b; } void out() { cout<<"The decremented elements of the object are: "<<endl<< a<<" and " <<b; }
}; int main() { OverLoad obj; obj.in(); --obj; obj.out(); return 0;
}
Output
Enter the first number : 56 ENter the second number : 234 The decremented elements fo the objects are: 55 and 223
Example 3: Overloading a NOT (!) operator
#include <iostream>
using namespace std; class NotOp { private: int a; bool b; public: NotOp() : a(0), b(true) {} void in() { cout << "Enter the first number : "; cin >> a; cout<< "Enter true or false : "; cin >> b; } // Overloading the NOT (!) operator void operator ! () { a= !a; b= !b; } void out() { cout<<"Output: "<<endl<< a<<endl<<b; }
}; int main() { NotOp obj; !obj; obj.out(); return 0;
}
Output 1
0
Difference between Member and friend function
Member function:
- The number of parameters to be passed is reduced by one, as the calling object is implicitly supplied is an operand.
- Unary operators tales no explicit parameters.
- Binary operators take only one explicit parameter.
Friend Function:
- More parameters can be passed.
- Unary operators take one explicit parameter.
- Binary operators take two explicit parameters.
What are the rules for operator overloading in C++?
- To work, at least one of the operands must be a user-defined class object.
- We can only overload the existing operators, Can’t overload new operators.
- Some operators cannot be overloaded using a friend function. However, such operators can be overloaded using the member function.
Which operators Cannot be overloaded?
- Conditional [?:], size of, scope(::), Member selector(.), member pointer selector(.*) and the casting operators.
- We can only overload the operators that exist and cannot create new operators or rename existing operators.
- At least one of the operands in overloaded operators must be user-defined, which means we cannot overload the minus operator to work with one integer and one double. However, you could overload the minus operator to work with an integer and a mystring.
- It is not possible to change the number of operands of an operator supports.
- All operators keep their default precedence and associations (what they use for), which cannot be changed.
- Only built-in operators can be overloaded.
Advantages of an operator overloading in C++
- Operator overloading in c++ enables programmers to use notation closer to the target domain.
- They provide similar support to built-in types of user-defined types.
- Operator overloading in c++ makes the program easier to understand.
Disadvantages of an operator overloading in C++
In operator overloading, any C++ existing operations can be overloaded, but some exceptions.
The need for operator overloading in C++
It allows us to provide an intuitive interface to our class users, plus makes it possible for templates to work equally well with classes and built-in types. Operator overloading allows C++ operators to have user-defined meanings on user-defined types or classes.
The syntax for operator overloading:
Class class_name { …………………. ………………….. Public Return_type operator symbol (argument ()) { ………………. ………………. } ………………………….
};
Unary Operators and Binary Operator overloading
Unary operators:
- Operators which work on a single operand are called unary operators.
- Examples: Increment operators(++), Decrement operators(–),unary minus operator(-), Logical not operator(!) etc…
Binary operators:
- Operators which works on Two operands are called binary operator.
Operator Overloading in Unary Operators
We can overload a unary operator like any other operator. We can redefine the unary operators to behave in a certain way on certain operands using unary operator overloading in C++. It is basically used for operating on user-defined datatypes, like classes and structures.
Example: Let us try overloading the increment and decrement operators through a C++ program.
#include<iostream>
using namespace std; class UnaryOverload
{ int hr, min; public: void in() { cout<<"\n Enter the time: \n"; cin>>hr; cout<<endl; cin>>min; } void operator++(int) //Overload Unary Increment { hr++; min++; } void operator--(int) //Overload Unary Decrement { hr--; min--; } void out() { cout<<"\nTime is "<<hr<<"hr "<<min<<"min"; }
};
int main()
{ UnaryOverload ob; ob.in(); ob++; cout<<"\n\n After Incrementing : "; ob.out(); ob--; ob--; cout<<"\n\n After Decrementing : "; ob.out(); return 0;
}
Output
Enter the time: 5
56
After Incrementing:
Time is 6hr 57 mins
After Decrementing:
Time is 4hr 55 min
Operator Overloading in Binary Operators
We can redefine the binary operators to operate in a certain way for user-defined objects. The binary operators are the operators that work on two operands, such as addition (+), multiplication (*), etc. A single operator can carry out a variety of functionalities using two operands provided by the programmer or user in this polymorphic compile technique.
Example: Let us see the following C++ code that elaborates the overloading of the addition operator.
#include <iostream>
using namespace std; class Time { private: int hour; int minute; public: Time() : hour(0), minute(0) {} void in() { cout << "Enter the time: "; cin >> hour; cin >> minute; } // Overload the + operator Time operator + (const Time & obj) { Time temp; temp.hour = hour + obj.hour; temp.minute = minute + obj.minute; if (temp.minute>=60) { temp.hour+=1; temp.minute-=60; } if (temp.hour>24) temp.hour=1; return temp; } void out() { cout<<"Time is "<< hour<<"hrs "<<minute<<"min"; }
}; int main() { Time T1, T2, result; cout << "Enter first time in hours and minutes one by one :\n"; T1.in(); cout << "Enter second time in hours and minutes one by one :\n"; T2.in(); // T1 calls the operator function // T2 is passed as an argument to the function result = T1 + T2; result.out(); return 0;
}
Output
Enter first time in hours and minutes one by one:
Enter the time:11
56
Enter second time in hours and minutes one by one:
Enter the time: 2
10
Time is 14hrs 6 min
Overloadable/Non-overloadable Operators
Now that you saw the overloading of unary and binary operators in C++ in the previous sections of this blog, you must know that not all operators can be overloaded. The operators that can be overloaded in C++ are known as overloadable operators. However, there are some non-overloadable operators as well that can’t be overloaded.
The list of non-overloadable operators goes as follows:
- Ternary operator (? 🙂
- Dot operator or member access operator (.)
- Pointer to member operator (.*)
- Scope resolution operator ( :: )
- Object type operator (typeid)
- Object size operator (sizeof)
These operators cannot be overloaded because doing so will cause significant programming problems. As an illustration, the sizeof operator returns the operand, which is the size of the object or datatype. The compiler evaluates this. It cannot be assessed in real-time. We can’t thus overburden it.
Overloading special operators in C++
Some of the special operators in C++ are as follows:
- new – It is used to allocate the memory dynamically.
- Delete – It is used to free the memory dynamically.
- [] – It is a subscript operator.
- -> – – It is a member access operators.
- = – It is used to assign the values.
- () – It is used for function call.
The operators other than listed above can be overloaded either as a member or as non-members. But in general, non-member overloading is recommended. Because:
- Symmetry: When a binary operator is defined as a class method, it must have objects as its operands. We should write like complex*5 but not like 5*complex because 5. operator*(complex)does not make any sense. In other words, a*b should be the same as b*a. Otherwise, it breaks the cumulativeness that the user is expecting from the *operator. So, in this case, we should use no-member operators overloading.
- Weak coupling: since a non-member method cannot access private member, it tends to make the class less coupled
Example:
Using unary operator: //Overload ++ when used as prefix
#include<iostream.h>
Using namespace std;
Class count
{ Private: Int value; Public:
//constructor to initialize count to 5
Count() : value(5) {}
//overload ++ when used as prefix
Void operator ++ () { ++value;
}
Void display()
{
Cout<<”Count: “<<value<<endl;
}
};
Int main()
{
Count count1;
//call the “void operator ++ ()” function
++count1:
Count1.display();
Return 0;
}
Output Count: 6
NOTE: Here, When we use ++count1; , the void operator ++() is called. This increases the value attribute for the object count 1 by 1. When we overload the operators, we can use them to work in any way we like. For example, we could have used ++ to increase the value by 100. However, this makes our code more confusing and difficult to understand. So using operators in overloading correctly and consistently, and understandably helps easy to understand without any difficulties. The above-given example works when ++ is used as a prefix to make ++ works as a postfix; we use this syntax. Syntax: Here, the int inside the parentheses. It’s the syntax used for using unary operators as postfix; it’s not a function parameter.
Example 2:
//C++ program to overload the binary operator +
//This program adds two complex numbers #include<iostream.h>
using namespace std; class Complex
{ Private: float real; float imag;
Public:
//constructor to initialize real and imag to 0
Complex() : real(0), image(0) {} void input()
{ // overload the + operator
Complex operator + (const Complex7 obj)
{
Complex temp;
temp.real = real +obj.real;
temp.imag = imag +obj.imag;
return temp;
} void output()
{
If(imag<0) Cout<< “OutputComplex number: ” << real << “i”;
else
count<< “Output Complex number: “<< “+” << “I”;
}
};
Int main()
{
Complex complex1, complex2,result;
Cout<< “Enter first complex number:\n;
Complex1.input();
Cout<< “Enter second complex number:\n”;
Complex2.input(); //complex1 calls the operator function
//complex2cis passed as an arguments to the function
result = complex1 + complex2;
result.output();
}
Output:
Enter a first complex number:
Enter real and imaginary parts respectively: 9 5
Enter a second complex number:
Enter real and imaginary parts respectively: 7 ^
Output Complex number: 16+11i
In this program, the operator function is:
Complex operator + (const Complex7 obj)
We can also write this function like:
Complex operator + (Complex obj)
{
//code
}
Access specifiers
Every member of a class is specified by 3 levels of access protection. These are used to define the scope of members of a class.
The access specifiers are indicated by using the keywords:
- Private
- Public
- Protected
- Private: Private access means member data written under this section is accessible by only member functions. They cannot be accessed from outside the class or anywhere in the program. If no access specifiers are mentioned, then by default, members are treated as private.
- Public: It means that members can be accessed by any function inside or outside the class, but within a program. The private variable height is accessed through the member function. Some of the public function of a class provides an interface for accessing the private and protected class members.
- Protected: The class members of this section are accessible by the member functions of the same class, friends of the class, and member functions derived from this class. The members cannot be accessed from outside; It is similar to the private members.
Operator Overloading in C++ FAQs
An operator is overloaded in this type of polymorphism to give it the user-defined semantics. Function overloading and operator overloading are two terms used in C++ to describe the ability to specify multiple definitions for a function name or an operator in the same scope
For the most part, C++’s built-in operators can have their functions redefined or overloaded. Both globally and by class, these operators may be overloaded. Embedded as functions, overloaded operators might be global or member functions.
In a form of polymorphism known as operator overloading, object-oriented systems permit the use of the same operator name or symbol for a number of different operations. In other words, it enables the operator symbol or name to be connected to many operator implementations.
The process of changing the functionality of some specific operators to do a new task is known as operator overloading. Types or approaches of operator overloading are as follows:
Overloading of unary operators
Overloading of binary operators
Overloading of binary operators using friend function (friend keyword is used to declare the class scope within a function)
When one or both operands are of a user-defined class or structure type, operator overloading makes it easier to specify user-defined implementation for such operations. This makes user-defined types more similar to the basic primitive data types in terms of behaviour.
One of the fundamental ideas of object-oriented programming (OOP), polymorphism addresses circumstances where something happens in a variety of ways. It refers to the idea in computer science that you can access objects of many types through the same interface.
It makes it feasible for templates to function equally well with classes and built-in/intrinsic types while also enabling you to present users of your class with an intuitive user interface. C/C++ operators can have user-defined meanings on user-defined types thanks to operator overloading like classes.
When an operator is overloaded, its original operational meaning might be expanded upon. On the other hand, we can construct a method so that it can be called in a variety of ways by using function overloading (also known as method overloading).
This brings us to the end of the blog on Operator Overloading in C++. Hope this helps you to up-skill your C++ skills. To learn more about programming and other related concepts, check out the courses on Great Learning Academy.
Also, if you are preparing for Interviews, check out these Interview Questions for C++ to ace it like a pro.
For a certificate in C++, take the free course on C++. If you want to deep dive further, do check out our Software Engineering Courses at Great Learning in collaboration with top engineering colleges and universities, including IIT Madras, Great Lakes & IIIT Hyderabad. Participate in regularly organized career accelerated programs and placement drives offered by Great Learning and get hired by the top leading companies across different industries.
Source: GreatLearning Blog