0% found this document useful (0 votes)
85 views

Operator Overloading

1. Operator overloading allows defining special behaviors for operators (like +, -, etc.) when used with user-defined types. This is done by creating operator functions. 2. Operator functions can be member functions or non-member (friend) functions. Member functions take the class object as the implicit first parameter, while friend functions require all parameters to be explicit. 3. Common operators that are overloaded include +, -, *, /, ++, --, =, etc. This allows user-defined types to be used with operators in the same way as built-in types.

Uploaded by

Dhanraj Kumar
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
85 views

Operator Overloading

1. Operator overloading allows defining special behaviors for operators (like +, -, etc.) when used with user-defined types. This is done by creating operator functions. 2. Operator functions can be member functions or non-member (friend) functions. Member functions take the class object as the implicit first parameter, while friend functions require all parameters to be explicit. 3. Common operators that are overloaded include +, -, *, /, ++, --, =, etc. This allows user-defined types to be used with operators in the same way as built-in types.

Uploaded by

Dhanraj Kumar
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 41

Operator Overloading

Module II
Operator Overloading
• Closely related to function overloading is operator overloading.
• In C++, you can overload most operators so that they perform special
operations relative to classes that you create.
• When an operator is overloaded, none of its original meanings are lost.
Instead, the type of objects it can be applied to is expanded.
• The ability to overload operators is one of C++'s most powerful
features.
• It allows the full integration of new class types into the programming
environment.
• After overloading the appropriate operators, you can use objects in
expressions in just the same way that you use C++'s built-in data types.
Operator Overloading
• You overload operators by creating operator functions.
• An operator function defines the operations that the overloaded
operator will perform relative to the class upon which it will work.
• An operator function is created using the keyword operator.
• Operator functions can be either members or nonmembers of a class.
• Nonmember operator functions are almost always friend functions of
the class.
• The way operator functions are written differs between member and
nonmember functions.
• Therefore, each will be examined separately, beginning with member
operator functions.
Operator Overloading
• For adding two objects of the same class we can use 3 ways
• d3.addobjects(d1, d2);
• d3 = d1.addobjects(d2);
• can be changed to the much more readable
• d3 = d1 + d2; using operator overloading
• The following operators are not overloaded in C++
• ?: (conditional)
• . (member selection)
•.* (member selection with pointer-to-member)
•:: (scope resolution)
•sizeof (object size information)
Creating a Member Operator Function
• A member operator function takes this general form:
ret-type class-name::operator#(arg-list)
{
// operations
}
Consider the class loc
class loc {
int longitude, latitude;
public:
loc() {}
loc(int lg, int lt) {
longitude = lg;
latitude = lt; }
void show() {
cout << longitude << " ";
cout << latitude << "\n"; } ……..};
member operator function
loc operator+(loc op2); //binary plus means obj1=obj1+obj2
loc operator*(int val); //multiply with integer
loc operator-(loc op2); //binary minus
void operator-(); //unary minus
loc operator=(loc op2); //assignment
loc operator++(); // prefixincrement
loc operator++(int); // postfix increment
loc operator—(); //prefix decrement
loc operator—(int);//postfix decrement
// Overload + for loc.
Overloading Binary Operators loc loc::operator+(loc op2)
#include <iostream> {
using namespace std; loc temp;
class loc { temp.longitude = op2.longitude + longitude;
int longitude, latitude; temp.latitude = op2.latitude + latitude;
public: return temp;
loc() {} }
loc(int lg, int lt) { int main()
longitude = lg; {
latitude = lt; } loc ob1(10, 20), ob2( 5, 30),ob3;
void show() { ob1.show(); // displays 10 20
cout << longitude << " "; ob2.show(); // displays 5 30
cout << latitude << "\n"; } ob1 = ob1 + ob2;// ob1=ob1.operator+(ob2);
loc operator+(loc op2); Ob3=ob2+ob1;//ob2.operator+(ob1);
}; ob3=ob1+ob2;//display
ob1.show(); // displays 15 50
return 0;
}
// Overload binary - for loc. // Overload unary minus - for loc.
loc loc::operator-(loc op2) loc loc::operator-( )
{ {
loc temp; longitude = -longitude;
// notice order of operands latitude = -latitude;
temp.longitude = longitude - op2.longitude; return (*this);
temp.latitude = latitude - op2.latitude; }
return temp; int main()
} {
loc ob1(10, -20),b2;
loc ob1(20,30),ob2(10,20); ob1.show(); // displays 10 20
ob1=ob1-ob2; b2=-ob1;
b2.show(); // displays -10 20
ob1.show();
}
// Overload assignment for loc. // Overload prefix ++ for loc.
loc loc::operator=(loc op2) loc loc::operator++()
{ {
longitude = op2.longitude; longitude++;
latitude = op2.latitude; latitude++;
return *this; // i.e., return object that return *this;
generated call }
} int main(){
int main(){ loc ob1(10, 20);
loc ob1(10, 20),ob2(1,2),ob3(90,90); ++ob1;
ob1 = ob2 =ob3; // multiple assignment ob1++;//error
ob1.show(); // displays 90 90 ob1.show(); // displays 11 21
ob2.show(); // displays 90 90 return 0;
return 0; }
}
Creating Prefix and Postfix Forms of the Increment and Decrement
Operators
• C++ allows you to explicitly create separate prefix and postfix versions
of increment or decrement operators.
• To accomplish this, you must define two versions of the operator++( )
function.
• One is defined as shown in the foregoing program.
• The other is declared like this:
loc operator++(int x);
// in main
ob++;
//prefix int main(){
loc loc::operator++() loc ob1(10, 20),ob2(1,2),ob3;
{ ++ob1;//ob1.operator++();
longitude++; ob1.show();
latitude++; ob2++;//ob2.operator++(int);
return *this; ob2.show();
} ob3=++ob1;
//postfix ob3.show();
loc loc::operator++(int) ob1.show();
{ ob3=ob2++;
loc temp=*this; ob3.show();
longitude++; ob2.show();
latitude++;
return temp;
}
loc loc::operator*(int val) // in main
{ ob3=ob3*5;//ob3=ob3.operator*(5);
longitude=longitude*val; ob3.show();
latitude=latitude*val; ob3=5*ob3;//error
return *this; }
}
Friend Function
• Friend functions play a very important role in operator overloading by
providing the flexibility denied by the member function of a class.
• They allow overloading of stream operators(<< or >>)
• The only difference between friend function and a member function is
that the friend function requires the arguments to be explicitly passed
to the function and processes them explicitly
• where as the member function considers the first argument implicitly.
Using friend function
#include <iostream>
using namespace std;
class loc {
int longitude, latitude;
public:
loc() {longitude=0;latitude=0;}
loc(int lg, int lt)
{
longitude = lg;
latitude = lt;
}
void show()
{
cout << longitude << " ";
cout << latitude << "\n";
}
Using friend function operator overloading
friend loc operator+(loc op1,loc op2); //binary plus means obj1=obj1+obj2
friend loc operator*(loc op1,int val); //multiply with integer
friend loc operator-(loc op1,loc op2); //binary minus
friend void operator-(loc &op1); //unary minus
friend loc operator+(loc op1, int op2);
friend loc operator+(int op1, loc op2);

friend loc operator++(loc &op1); // prefixincrement


friend loc operator++(loc &,int); // postfix increment
friend loc operator--(loc &); // prefixdecrement
friend loc operator--(loc &,int); // postfix decrement
friend istream & operator >>(istream &in, loc &ob);
friend ostream & operator <<(ostream &out, loc &ob);
};
Using friend function overloading of binary +
loc operator+(loc op1,loc op2)
{
loc temp;
temp.longitude = op1.longitude + op2.longitude;
temp.latitude = op1.latitude + op2.latitude;
return temp;
}
//ob1=operator+(ob1,ob2);
//In main
{
loc ob1(10,10),ob2(20,20);
ob1=ob1+ob2;
}
Using friend function overloading of binary -
loc operator-(loc op1,loc op2)
{
loc temp;
temp.longitude = op1.longitude - op2.longitude;
temp.latitude = op1.latitude - op2.latitude;
return temp;
}

// ob2=ob1-ob2;
Using friend function overloading of binary *
loc operator*(loc op1,int val) int main()
{ {
loc temp;
temp.longitude = op1.longitude*val; loc ob1(20,20);
temp.latitude = op1.latitude * val; ob1=ob1*2;
return temp; ob1=2*ob1;
}
loc operator*(int val,loc op1)
{ }
loc temp;
temp.longitude = op1.longitude*val;
temp.latitude = op1.latitude * val;
return temp;
}
Using friend function overloading of unary -
void operator-(loc &op1)
{
op1.longitude=-op1.longitude;
op1.latitude=-op1.latitude;
}

//main
-ob1;
ob1.show();
Using friend function overloading of unary ++( prefix increment)
loc operator++(loc &op1)
{
op1.longitude=op1.longitude+1;
op1.latitude++;
return op1;
}
//in main
++ob1;
Using friend function overloading of unary ++(postfix increment)
loc operator++(loc &op1,int)
{
loc temp(op1);
op1.longitude=op1.longitude+1;
op1.latitude++;
return temp;
}
//In main
ob2=ob++; //10 10
ob2.show(); //10 10
ob.show(); // 11 11
Using friend function overloading of unary –( prefix decrement)
loc operator--(loc &op1)
{
--op1.longitude;
--op1.latitude;
return op1;
}
Using friend function overloading of unary –(postfix decrement)
loc operator--(loc &op1,int)
{
loc temp=op1;
op1.longitude--;
op1.latitude--;
return (temp);
}
Overloading extraction operator >> using friend function
Overloading extraction operator >> using friend function
istream & operator >>(istream &in, loc &ob)
{
cout<<"Enter longitude and latitude"<<endl;
in>>ob.longitude;
in>>ob.latitude;
return in;
}
//In main
loc ob3
cout<<"enter values for ob3"<<endl;
cin>>ob3; // operator>>(cin,ob3);
Overloading of Insertion operator << using Friend function
Overloading of Insertion operator << using Friend function
ostream & operator <<(ostream &out, loc &ob)
{
out<<"The objects member variables are"<<endl;
out<<ob.longitude<<"-"<<ob.latitude<<endl;
return out;
}
//in main
cout<<ob3;// operator<<(cout,ob3); as ob3.show();
cout<<ob1;
Manipulation of sting using operator Overloading
Header files String1 :: String1(){
using namespace std; cout << "<Inside default constructor.>"<<endl;
class String1{ len = 0;
char *name; name = new char[1];
int len; name[0] = '\0‘;
public: }
String1(); String1 :: String1(const char *s)
String1(const char *s); {
String1(const String1 &s); cout << "<Inside parameterised
String1 operator=(const String1 &s); constructor.>"<<endl;
String1 operator+(const String1 &s); len=strlen(s);
bool operator == (String1 ss) ; name = new char[len+1];
void display() const; strcpy(name,s);
}; }
Manipulation of sting using operator Overloading
String1 String1::operator=(const String1& s) {
String1 :: String1(const String1& s) { cout<<"Inside assignment ..."<<endl;
len=strlen(s.name); len=strlen(s.name);
name = new char[len+1]; name=new char[len+1];
strcpy(name,s.name); strcpy(name,s.name);
} return s;
void String1 :: display() const }
{ Instead of strcpy() also can write
cout<<"name: " <<name<<" "<<"lenth: for (int i=0; i<size; i++) {
"<<len<<endl; name[i] = s[i];}
} name[size] = '\0';
String1 :: ~String1()
{
delete [] name;
}
String Manipulation
Note : String1 *p1=new String1(“Institute");
int main (){ String1 *p2=new String1(*p1);
String1 s2; p1->display();
String1 s1(“Heritage”); p2->display();
s1.display(); *p2=*p1;// what happened
String1 s3=s1; p1->display();
s3.display(); p2->display();
String1 s4(s3); p2=p1; // what happened
s4.display(); delete p1;
s2=s4; delete p2;
s2.display();
Assignment operator overload ( two way)
bool String1 :: operator == (String1 ss) { bool String1 :: operator == (String1 &s){
return ( strcmp(name, ss.name)==0 ) ? true : false; if (this->len != s.len) {
} return false;
Note }
int main (){ for (int i=0; i<s.len; i++) {
String1 s1(“Heritage”); if ((this->len)[i] != (s.len)[i]) {
s1.display(); return false;
String1 s2=s1; }
s2.display(); }
if (s1 == s2) { return true;
cout << “Strings are equal\n"; }
} else {
cout << “Strings are not equal\n";
………..
}
Overloading + operator for sting concatenation
String operator+(const String& s1, const Note :
String& s2) int main (){
{ String1 str1(“Heritage”);
String temp; String1 str2(“Institute”),str3;
temp.len=s1.len+s2.len; str3=str1+str2;
temp.name=new char[temp.len+1]; str3.display();
strcpy(temp.name,s1.name); …………..
strcat(temp.name,” “);
strcat(temp.name,s2.name);
return temp;
}
Overloading new and delete
• New and 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 only 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.
• Syntax
void *operator new(size_t size)
• 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.
Overloading new and delete
void *operator new(size_t size) • In the new overloaded function, dynamic
memory is allocated through new operator, but
{ it should be global new operator otherwise it
cout<<"overloading new"<<endl; will go in recursion
• void *p = new String();
void *p=::new String();
• // this will go in recursion as new will be
Or overloaded again and again
//void*p=malloc(size); for global • void *p = ::new String(); // this is correct
overloading
return p; • For global overloading
}
//in main • //in main
String *p=new String("Technology"); int *p=new int[5];
char *s=new char[20];
p->display();
Overloading new and delete
• Syntax
void operator delete(void *)
• The function receives a parameter of type void* which has to be
deleted. Function should not return anything.

void operator delete(void *p)


{
cout<<"overloading delete"<<endl;
free(p) ; or
::delete p;
}
//in main
delete p;
Main function
int main() str4.display();
{ if(str1==str2)
String str1("Heritage"),str3,str4; cout<<"two string equal"<<endl;
cout<<"Str1 is: "<<endl; else
str1.display(); cout<<"two string not equal"<<endl;
String str2="Institute"; if(str3==str4)
cout<<"Str2 is: "<<endl; cout<<"two string equal"<<endl;
str2.display(); else
str3=str1+str2; cout<<"two string not equal"<<endl;
cout<<"str3 is"<<endl; return 0;
str3.display(); }
str4=str3;
Overloading subscript or array index [] operator
• The subscript operator [] is normally used to access array elements.
This operator can be overloaded to enhance the existing functionality
of C++ arrays.
• Following are some useful facts about overloading of [].
• Overloading of [] may be useful when we want to check for index out
of bound.
• We must return by reference in function because an expression like
“arr[i]” can be used an lvalue.
Overloading array index [] operator
#include <iostream> int &operator[](int i) {
using namespace std; if( i > SIZE ) {
const int SIZE = 10; cout << "Index out of bounds" <<endl;
return arr[0];
class Array { }
private: return arr[i];
int arr[SIZE]; }
};
public: int main() {
Array() { Array A;
int i; cout << "Value of arr[2] : " << A[2] <<endl;
for(i = 0; i < SIZE; i++) { cout << "Value of arr[5] : " << A[5]<<endl;
arr[i] = i; cout << "Value of arr[12] : " << A[12]<<endl;
} return 0;
} }
Overloading function call ()
loc operator()(int a,int b) void operator()(int i,int j,int k) {
{
loc ob1; arr[0]=arr[0]+i;
ob1.longitude =longitude+ a*100; arr[1]=arr[1]+j;
ob1.latitude = latitude+b*100; arr[2]=arr[2]+k;
return ob1;
} }
//In main //in main
loc ob1(10, 20),ob3; Array A;
ob3=ob3(10,10); A(10,20,30);
ob3.show();// cout<<A[0]<<endl;//10
cout<<A[1]<<endl;//21
cout<<A[2]<<endl;//32
Question Overload * to multiply two matrices (using dynamic memory allocation)

class Matrix{ ~Matrix (){


int rows;
int cols; cout<<"destructor"<<endl;
int **Mat; for(int i =0;i<rows;i++)
public: delete [] Mat[i];
Matrix(){cout<<"default"<<endl;rows=0;cols=0;} delete [] Mat;
Matrix (const int rows, const int cols); }
Matrix(const Matrix &o); };
Matrix &operator=(const Matrix &o );
Matrix operator *(const Matrix &o);
friend ostream &operator<<(ostream &os, Matrix &m);
friend istream &operator>>(istream &os, Matrix &m);
Matrix::Matrix(const int row,const int col ) Matrix::Matrix(const Matrix &o)
{ {
cout<<“ Parameterized constructor"<<endl; cout<<"copy constructor"<<endl;
rows=row; cols=o.cols;
cols=col; rows=o.rows;
Mat=new int* [rows]; Mat=new int* [o.rows];
for(int i =0;i<rows;i++) { for(int i =0;i<o.rows;i++) {
Mat[i]=new int[cols]; Mat[i]=new int[o.cols];
} }
for(int i=0;i<rows;i++) for(int i=0;i<o.rows;i++)
for(int j=0;j<cols;j++) for(int j=0;j<o.cols;j++)
Mat[i][j]=0; Mat[i][j]=o.Mat[i][j];
}
}

Do remaining part of code to execute the program successfully.

You might also like