Operator Overloading in C++
Operator Overloading in C++
C++ provides a special function to change the current functionality of some operators within its
class which is often called as operator overloading. Operator Overloading is the method by
which we can change the function of some specific operators to do some different task.
In C++, we can make operators to work for user defined classes. This means C++ has the
ability to provide the operators with a special meaning for a data type, this ability is known as
operator overloading.
For example, we can overload an operator ‘+’ in a class like String so that we can concatenate
Other example classes where arithmetic operators may be overloaded are Complex Number,
Function Body
In the above syntax Return_Type is value type to be returned to another object, o perator op is
the function where the o perator is a keyword and op is the operator to be overloaded.
Below are some criteria/rules to define the operator function:
● In case of a non-static function, the binary operator should have only one
argument and unary should not have an argument.
● In the case of a friend function, the binary operator should have only two
argument and unary should have only one argument.
● All the class member object should be public if operator overloading is
implemented.
● Operators that cannot be overloaded are . .* :: ? :
● Operator cannot be used to overload when declaring that function as friend
function =
() [] - >.
1. Overloading Unary Operator: Let us consider to overload (-) unary operator. In
unary operator function, no arguments should be passed. It works only with one
class objects. It is a overloading of an operator operating on a single operand.
Example:
Assume that class Distance takes two member object i.e. feet and inches, create
a function by which Distance object should decrement the value of feet and
inches by 1 (having single operand of Distance Type).
#include <iostream.h>
class Distance {
public:
int feet, inch; // Member Object
Distance(int f, int i) // Constructor to initialize the object's value
{
this->feet = f;
this->inch = i;
}
// Overloading(-) operator to perform decrement operation of Distance object
void operator-()
{
feet--;
inch--;
cout << "\nFeet & Inches(Decrement): " << feet << "'" << inch;
}
};
int main()
{
Distance d1(8, 9); // Declare and Initialize the constructor
-d1; // Use (-) unary operator by single operand
return 0;
}
Output:
Feet & Inches(Decrement): 7'8
1. In the above program, it shows that no argument is passed and no return_type
value is returned, because unary operator works on a single operand. (-) operator
change the functionality to its member function.
Note: d2 = -d1 will not work, because operator-() does not return any value.
2. Overloading Binary Operator: In binary operator overloading function, there should
be one argument to be passed. It is overloading of an operator operating on two
operands.
Let’s take the same example of class Distance, but this time, add two distance
objects.
// C++ program to show binary operator overloading
#include <iostream.>
public:
{
this->feet = 0;
this->inch = 0;
}
{
this->feet = f;
this->inch = i;
}
{
}
};
int main()
{
Distance d1(8, 9);// Declaring and Initializing first object
Distance d2(10, 2); // Declaring and Initializing second object
Distance d3; // Declaring third object
d3 = d1 + d2; // Use overloaded operator
// Display the result
cout << "\nTotal Feet & Inches: " << d3.feet << "'" << d3.inch;
return 0;
}
Output:
Total Feet & Inches: 18'11
1.
Here in the above program,
See Line no. 26, D istance operator+(Distance &d2), here return type of function is
distance and it uses call by references to pass an argument.
See Line no. 49, d 3 = d1 + d2; here, d1 calls the operator function of its class
object and takes d2 as a parameter, by which operator function return object and
the result will reflect in the d3 object.
Pictorial View of working of Binary Operator:
2. Overloading Binary Operator using a Friend function: In this approach, the
operator overloading function must precede with friend keyword, and declare a
function class scope. Keeping in mind, friend operator function takes two
parameters in a binary operator, varies one parameter in a unary operator. All the
working and implementation would same as binary operator function except this
function will be implemented outside of the class scope.
Let’s take the same example using the friend function.
#include <iostream>
public:
// Member Object
// No Parameter Constructor
Distance()
{
this->feet = 0;
this->inch = 0;
}
{
this->feet = f;
this->inch = i;
}
};
{
Distance d3;
}
int main()
{
Distance d1(8, 9); // Declaring and Initializing first object
Distance d2(10, 2); // Declaring and Initializing second object
Distance d3; // Declaring third object
d3 = d1 + d2; // Use overloaded operator
// Display the result
cout << "\nTotal Feet & Inches: " << d3.feet << "'" << d3.inch;
return 0;
}
Output:
Total Feet & Inches: 18'11
Here in the above program, operator function is implemented outside of class scope by
declaring that function as the friend function.
In these ways, an operator can be overloaded to perform certain tasks by changing the
functionality of operators.
#include<iostream>
using namespace std;
class Complex
{
private:
int real, imag;
public:
Complex(int r = 0, int i =0) //{real = r; imag = i;}
// This is automatically called when '+' is used with between two Complex objects
Complex operator + (Complex const &obj)
{
Complex res;
res.real = real + obj.real;
res.imag = imag + obj.imag;
return res;
}
void print() { cout << real << " + i" << imag << endl; }
};
int main()
{
Complex c1(10, 5), c2(2, 4);
Complex c3 = c1 + c2; // An example call to "operator+"
c3.print();
}
Output:
12 + i9
Operator functions are same as normal functions. The only differences are, name of an
operator function is always operator keyword followed by symbol of operator and operator
#include<iostream.h>
class Complex
{
private:
int real, imag;
public:
Complex(int r = 0, int i =0) //{real = r; imag = i;}
void print()
{
cout << real << " + i" << imag << endl;
}
// The global operator function is made friend of this class so that it can access private
members
friend Complex operator + (Complex const &, Complex const &);
};
Complex operator + (Complex const &c1, Complex const &c2)
{
return Complex(c1.real + c2.real, c1.imag + c2.imag);
}
int main()
{
Complex c1(10, 5), c2(2, 4);
Complex c3 = c1 + c2; // An example call to "operator+"
c3.print();
return 0;
}
Can we overload all operators?
Almost all operators can be overloaded except few. Following is the list of operators that
cannot be overloaded.
. (dot)
::
?:
sizeof
1) For operator overloading to work, at least one of the operands must be a user defined class
object.
2) A
ssignment Operator: Compiler automatically creates a default assignment operator with
every class. The default assignment operator does assign all members of right side to the left
side and works fine most of the cases (this behavior is same as copy constructor). See this
3) C
onversion Operator: We can also write conversion operators that can be used to convert
#include <iostream.h>
class Fraction
{
int num, den;
public:
}
};
return 0;
}
Output:
0.4
Overloaded conversion operators must be a member method. Other operators can either be
4) Any constructor that can be called with a single argument works as a conversion
constructor, means it can also be used for implicit conversion to the class being constructed.
#include<iostream>
private:
int x, y;
public:
x = i; y = j;
}
void print() {
cout << endl << " x = " << x << ", y = " << y;
}
};
t.print();
t.print();
return 0;
}
Output:
x = 20, y = 20
x = 30, y = 0
We will soon be discussing overloading of some important operators like new, delete, comma,
1) Only built-in operators can be overloaded. New operators can not be created.
4) Overloaded operators cannot have default arguments except the function call operator ()
defined type.
6) Assignment (=), subscript ([]), function call (“()”), and member selection (->) operators must
7) Except the operators specified in point 6, all other operators can be either member
8 ) Some operators like (assignment)=, (address)& and comma (,) are by default overloaded.
Delete operators can be overloaded globally or they can be overloaded for specific classes.
● If these operators are overloaded using member function for a class, it means
that these operators are overloaded o
nly for that specific class.
● If overloading is done outside a class (i.e. it is not a member function of a class),
the overloaded ‘new’ and ‘delete’ will be called anytime you make use of these
operators (within classes or outside classes). This is global overloading.
The overloaded new operator receives size of type size_t, which specifies the number of bytes
of memory to be allocated. The return type of the overloaded new must be void*.The
overloaded function returns a pointer to the beginning of the block of memory allocated.
Syntax for overloading the delete operator :
The function receives a parameter of type void* which has to be deleted. Function should not
return anything.
NOTE: Both overloaded new and delete operator functions are static members b
y default.
// CPP program to demonstrate Overloading new and delete operator for a specific class
#include<iostream>
#include<stdlib.h>
using namespace std;
class student
{
string name;
int age;
public:
student()
{
cout<< "Constructor is called\n" ;
}
student(string name, int age)
{
this->name = name;
this->age = age;
}
void display()
{
cout<< "Name:" << name << endl;
cout<< "Age:" << age << endl;
}
void * operator new(size_t size)
{
cout<< "Overloading new operator with size: " << size << endl;
void * p = ::new student();
//void * p = malloc(size); will also work fine
return p;
}
void operator delete(void * p)
{
cout<< "Overloading delete operator " << endl;
free(p);
}
};
int main()
{
student * p = new student("Yash", 24);
p->display();
delete p;
}
Overloading new operator with size: 16
Constructor is called
Name:Yash
Age:24
Overloading delete operator
NOTE: In the above new overloaded function, we have allocated dynamic memory through
new operator, but it should be global new operator otherwise it will go in recursion
void *p = new student(); // this will go in recursion asnew will be overloaded again and again
#include<iostream>
#include<stdlib.h>
{
void * p = malloc(size);
return p;
}
{
free(p);
}
int main()
{
int n = 5, i;
p[i]= i;
delete p;
}
Output :
Array: 0 1 2 3 4
NOTE: In the code above, in new overloaded function we cannot allocate memory using ::new
1. The overloaded new operator function can accept arguments; therefore, a class
can have multiple overloaded new operator functions. This gives the programmer
more flexibility in customizing memory allocation for objects. For example:
void *operator new(size_t size, char c)
{
void *ptr;
ptr = malloc(size);
if (ptr!=NULL)
*ptr = c;
return ptr;
}
main()
{
char *ch = new('#') char;
}
NOTE:
1. Code will not only allocate memory for single character but will also initialize the
allocated memory with # character.
2. Overloaded new or delete operators also provide Garbage Collection for class’s
object.
3. Exception handling routine can be added in overloaded new operator function.
4. Sometimes you want operators new and delete to do something customized that
the compiler-provided versions don’t offer. For example, You might write a custom
operator delete that overwrites deallocated memory with zeros in order to
increase the security of application data.
5. We can use realloc() function in new function to re-allocate memory dynamically.
6. Overloaded new operator also enables programmers to squeeze some extra
performance out of their programs. For example, In a class, to speed up the
allocation of new nodes, a list of deleted nodes is maintained so that their
memory can be reused when new nodes are allocated.In this case, the overloaded
delete operator will add nodes to the list of deleted nodes and the overloaded new
operator will allocate memory from this list rather than from the heap to speedup
memory allocation. Memory from the heap can be used when the list of deleted
nodes is empty.
C++.
Example:
● To concatenate two strings using unary operator overloading. Declare a class with
two string variables.
● Create an instance of the class and call the Parametrized constructor of the class
to initialize those two string variables with the input strings from the main
function.
● Overload the unary operator to concatenate these two string variables for an
instance of the class.
● Finally, call the operator function and concatenate two class variables.
● Declare a class with a string variable and an operator function ‘+’ that accepts an
instance of the class and concatenates it’s variable with the string variable of the
current instance.
● Create two instances of the class and initialize their class variables with the two
input strings respectively.
● Now, use the overloaded operator(+) function to concatenate the class variable of
the two instances.
Program to compare two Strings using Operator Overloading
Given two strings, how to check if the two strings are equal or not, using Operator
Overloading.
Examples:
● Declare a class with a string variable and operator function ‘==’, ‘<=' and '>=’ that
accepts an instance of the class and compares it’s variable with the string
variable of the current instance.
● Create two instances of the class and initialize their class variables with the two
input strings respectively.
● Now, use the overloaded operator(==, <= and >=) function to compare the class
variable of the two instances.
Below is the implementation of the above approach:
#include <cstring>
#include <iostream>
#include <string.h>
// Class to implement operator overloading function for concatenating the strings
class CompareString {
public:
// Classes object of string
char str[25];
// Parametrized Constructor
CompareString(char str1[])
{
// Initialize the string to class object
strcpy(this->str, str1);
}
// Overloading '==' under a function which returns integer 1/true if left operand string
// and right operand string are equal. (else return 0/false)
int operator==(CompareString s2)
{
if (strcmp(str, s2.str) == 0)
return 1;
else
return 0;
}
// Overloading '<=' under a function which returns integer 1/true
// if left operand string is smaller than or equal to the right operand string.
// (else return 0/false)
int operator<=(CompareString s3)
{
if (strlen(str) <= strlen(s3.str))
return 1;
else
return 0;
}
// Overloading '>=' under a function which returns integer 1/true
// if left operand string is larger than or equal to the right operand string.
//(else return 0/false)
int operator>=(CompareString s3)
{
if (strlen(str) >= strlen(s3.str))
return 1;
else
return 0;
}
};
void compare(CompareString s1, CompareString s2)
{
if (s1 == s2)
cout << s1.str << " is equal to "
<< s2.str << endl;
else {
cout << s1.str << " is not equal to "
<< s2.str << endl;
if (s1 >= s2)
cout << s1.str << " is greater than "
<< s2.str << endl;
else
cout << s2.str << " is greater than "
<< s1.str << endl;
}
}
void testcase1() // Testcase1
{
// Declaring two strings
char str1[] = "Geeks";
char str2[] = "ForGeeks";
// Declaring and initializing the class with above two strings
CompareString s1(str1);
CompareString s2(str2);
cout << "Comparing \"" << s1.str << "\" and \""<< s2.str << "\"" << endl;
compare(s1, s2);
}
void testcase2() // Testcase2
{
// Declaring two strings
char str1[] = "Geeks";
char str2[] = "Geeks";
// Declaring and initializing the class with above two strings
CompareString s1(str1);
CompareString s2(str2);
cout << "\n\nComparing \"" << s1.str << "\" and \""<< s2.str << "\"" << endl;
compare(s1, s2);
}
int main()
{
testcase1();
testcase2();
return 0;
}
Output:
Comparing "Geeks" and "ForGeeks"
Geeks is not equal to ForGeeks
ForGeeks is greater than Geeks