aravindakasukurthi.files.wordpress.com viewoperator overloading. the ability to overload operators...
TRANSCRIPT
Operator Overloading
The ability to overload operators is one of C++’s most powerful features. After overloading appropriate operators, you can use objects in expressions in
expressions in just the same way that you use C++’s built-in data types. You overload operators by creating operator functions. An operator function defines the operations that the overload 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.
Creating a member operator function
ret-type classname :: operator#(arg-list){
//operations}The # is a place holder.When you create an operator function, substitute the operator for the #.
Example: For + ------------ operator +
When you are overloading a unary operator, arg-list will be empty. When you are overloading binary operators, arg-list will contain one parameter. operator+() has only one parameter even though it overloads the binary + operator. The operand on the left side of the + is passed implicitly to the function through the
this pointer. The operand on the right is passed in the parameter op2. When binary operators are overloaded, it is the object on the left that generates the
call to the operator function. It is common for an overloaded operator function to return an object of the class it
operates upon. By doing so, it allows the operator to be used in larger expressions. It is important to understand that an operator function can return any type and that
the type returned depends solely upon your specific application. Operator+() function does not modify either operand. Because, the traditional use of
the + operator does not modify either operand.Example 4+5=9
Example program:
#include<iostream>using namespace std;class opload1{
int a,b;public:void read();opload1 operator+(opload1);void display();
};void opload1 :: read(){
cout<<"Enter a,b\n";cin>>a>>b;
}opload1 opload1 :: operator+(opload1 ob){
opload1 op3;op3.a=a+ob.a;op3.b=b+ob.b;return op3;
}void opload1 :: display(){
cout<<"a="<<a<<"\tb="<<b<<endl;}main(){
opload1 op1,op2,op3;op1.read();op2.read();op3=op1+op2;op3.display();
}
In C++, if the = is not overloaded, a default assignment operation is created automatically for any class you define.
The default assignment is simply a member-by-member, bitwise copy. The operator = () function returns *this, which is the object the generated the call. This arrangement is necessary is you want to be able to use multiple assignment
operations such as this:
ob1=ob2=ob3; //multiple assignment
opover opover :: operator=(opover op){
a=op.a;b=op.b;return *this; //return object that generated call.
}
To stay consistent with their original meanings.
Creating prefix and postfix forms of the increment and decrement operators
opover operator++(); //opover is class name //overload prefix ++ for opover. If the ++ preceeds its operand, the operator ++() function is called. If the ++ follows the operand, the operator ++ (int x) is called and x has the value
zero.
//prefix increment syntaxtype increment(){
//body of prefix operator}//postfix increment syntaxtype operator ++(int x){
//body of postfix operator}
Here, x is dummy argument which is used to differentiate between pre & post increment or decrement operators.
Example program:
// Overload pre, post increment#include<iostream>using namespace std;class opover{
public:int a;float b;opover(){
a=0;b=0;
}opover(int i,float j){
a=i;b=j;
}opover operator++(){
opover t;t.a=++a;t.b=++b;return t;
}opover operator++(int x){
opover t;t.a=a++;t.b=b++;return t;
}void display(){
cout<<"\na="<<a<<"\tb="<<b<<endl;}
};main(){
opover op1(4,5.6),op2(6,3.7),op3;op1.display();op2.display();
cout<<"After Pre increment\n";op3=++op1;op3.display();op1.display();
cout<<"After Post increment\n";op3=op1++;op3.display();op1.display();
}
Overloading the shorthand operators
You can overload any of C++’s “shorthand” operators, such as +=, -=, …
opload1 opload1 :: operator+=(opload1 ob){
a=ob.a+a;
b=ob.b+b;return *this;
} When overloading one of these operators, keep in mind that you are simply
combining an assignment with another type of operation.
Example program:
// Overloading Shorthand Assignment operators#include<iostream>using namespace std;class opover{
public:int a;float b;opover(){
a=0;b=0;
}opover(int i,float j){
a=i;b=j;
}opover opover :: operator+(opover op)
{opover t;t.a=a+op.a;t.b=b+op.b;return t;
}opover operator+=(opover op){
a=a+op.a;b=b+op.b;return *this;
}void operator-=(opover op){
a=op.a-a;b=op.b-b;
}
void display(){
cout<<"\na="<<a<<"\tb="<<b<<endl;}
};main(){
opover op1(4,5),op2(6,8);op1.display();op2.display();op1+=op2+op2;op1.display();op2-=op1;op2.display();
}
Operator overloading using a Friend function
You can overload an operator for a class by using a nonmember function, which is usually a friend of the class.
Since a friend function is not a member of the class, it does not have a this pointer.
Therefore an overloaded friend operator function is passed the operands explicitly.
When overloading a binary operator using a friend function, the left operand is passed in the first parameter and the right operand is passed in the second parameter.
Example:
friend opload operator+(opload,opload); //Now a friend
definition
opload1 operator+(opload1 op1,opload1 op2){opload1 t;t.a=op1.a+op2.a;t.b=op1.b+op2.b;return t;}
Example program:
// Overload + using friend
#include<iostream>using namespace std;class opover{
int a;float b;public:opover(){
a=0;b=0;
}opover(int i,float j){
a=i;b=j;
}friend opover operator+(opover,opover);void display(){
cout<<"\na="<<a<<"\tb="<<b<<endl;}
};opover operator+(opover ob1,opover ob2){
opover t;t.a=ob1.a+ob2.a;t.b=ob1.b+ob2.b;return t;
}main(){
opover op1(4,5.6),op2(6,3.7),op3;op1.display();op2.display();op3=op1+op2;op3.display();
}
There are some restrictions that apply to friend operator functions:
1. You may not overload the =, (), [], or -> operators by using a friend function.2. When overloading the increment or decrement operators, you will need to use a
reference parameter when using a friend function.
3. Because friend functions do not have this pointers.
Some operators cannot be overloaded by using member functions:
1. . (dot) operator2. :: (scope resolution) operator3. .* (pointer to class member) operator4. ?: (Ternary) operator
Using a friend to overload ++ or --
To overload increment or decrement operators using friend function you must pass the operand as a reference parameter. This is because friend functions do not have this pointer.
This causes any changes made to the parameter inside the function to affect the operand that generated the call.
Example program:
#include<iostream>using namespace std;class opover{
int a;float b;public:opover(){
a=0;b=0;
}opover(int i,float j){
a=i;b=j;
}friend opover operator++(opover&);friend opover operator--(opover&,int);void display(){
cout<<"\na="<<a<<"\tb="<<b<<endl;}
};opover operator++(opover &ob){
++ob.a;++ob.b;return ob;
}opover operator--(opover &ob,int x){
ob.a--;ob.b--;return ob;
}main(){
opover op1(4,5.6),op2(10,7.8),op3;op1.display();++op1;op1.display();op2.display();op2--;op2.display();
}
Friend operator functions to add flexibility
In many cases whether we overload an operator by using member operator function or friend operator function makes no functional difference.Whenever a binary operator is overloaded by member operator function the object on the left side of operator should be an object of the class.Assume a class defines a member operator+() function that adds an object of the class with an integer. If ob is an object of the class then the expression ob+10 is valid but the expression like 10+ob is invalid.The solution to the above problem is to overload the operator by using frien function. Therefore both the operations object+integer and integer+object are valid.
Example:
100+ob1; // this is possible with friend function only.
Example program from class notesor
#include<iostream>using namespace std;class complex
{int real;int imag;public:complex(){}complex(int x,int y){real=x;imag=y;}friend complex operator+(complex c,int x);friend complex operator+(int x,complex c);void display();};
complex operator+(complex c,int x){complex temp;temp.real=c.real+x;temp.imag=c.imag+x;return temp;}complex operator+(int x,complex c){complex temp;temp.real=x+c.real;temp.imag=x+c.imag;return temp;}void complex::display(){cout<<real<<"+i"<<imag;}main(){complex c1(1,2),c2(2,3),c3,c4;c3=c1+10;cout<<"\n addition=";c3.display();c4=10+c2;cout<<"\n 10+c2=";c4.display();}
Output:Addition of c1+10=11+i12Addition of 10+c2=12+i13
Overloading new, delete
It is possible to overload new and delete. You might choose to do this if you want to use some special allocation method.
For example, you may want allocation routines that automatically begin using a disk file as virtual memory when the heap has been exhausted.
The skeletons for the functions that overload new and delete are shown here:
// Allocate an object.void *operator new(size_t size){ /* Perform allocation. Throw bad_alloc on failure. Constructor called automatically. */
return pointer_to_memory;}
// Delete an object.void operator delete(void *p){
/* Free memory pointed to by p. Destructor called automatically. */}
The type size_t is a defined type capable of containing the largest single piece of memory that can be allocated. (size_t is essentially an unsigned integer.)
The parameter size will contain the number of bytes needed to hold the object being allocated. This is the amount of memory that your version of new must allocate.
The overloaded new function must return a pointer to the memory that it allocates. Beyond these constraints, the overloaded new function can do anything else you
require. When you allocate an object using new (whether your own version or not), the object's constructor is automatically called.
The delete function receives a pointer to the region of memory to be freed. It then releases the previously allocated memory back to the system. When an object is deleted, its destructor is automatically called.
Example Program:
// Overloading new, delete operators#include<iostream>
using namespace std;class student{
char name[20];int regdno;public:student(){
strcpy(name,"\0");regdno=0;
}student(char str[20],int r){
strcpy(name,str);regdno=r;
}void display(){ cout<<"\nMy name is "<<name<<"\tRegdno is "<<regdno<<"\n";}void *operator new(size_t size){
void *p;cout<<"\nOverloaded new operator size="<<size<<"\n";p=malloc(size);return p;
}void operator delete(void *p){
cout<<"\nOverloaded delete operator\n";free(p);
}};main(){
student *stu;stu = new student("abcd",1001);stu->display();delete stu;
}
Overloading new, delete for arrays
// new [] overloading Example program:
#include<iostream>using namespace std;class myclass{
int a,b;public:myclass(){
a=b=0;}myclass(int i,int j){
a=i;b=j;
}void read(){
cout<<"enter a,b\n";cin>>a>>b;
}void *operator new[](size_t size){
void *p;cout<<"new [] size="<<size<<endl;p=malloc(size);return p;
}void operator delete [](void *p){
free(p);}void *operator new(size_t size){
void *p;cout<<"new size="<<size<<endl;p=malloc(size);return p;
}void operator delete(void *p){
free(p);}void display(){
cout<<"a="<<a<<"\tb="<<b<<"\n";}
};main(){
myclass *p1,*p2;p2=new myclass(100,200);p2->display();p1=new myclass[4];for(int i=0;i<4;i++)p1[i].read();for(int i=0;i<4;i++)p1[i].display();delete p2;delete [] p1;
}
Overloading some special operators
C++ defines array subscripting, function calling, and class member access as operations. The operators that perform these functions are the [ ], ( ), and –>, respectively. One important restriction applies to overloading these three operators: They must be nonstatic member functions. They cannot be friends.
1. Overloading [] (index or subscript operator)
In C++, the [ ] is considered a binary operator when you are overloading it. Therefore,the general form of a member operator[ ]( ) function is as shown here:
type class-name::operator[](int i){// . . .}
Example program:
#include<iostream>using namespace std;class indexop{
int p[10];public:indexop()
{
}void read(int);int operator[](int i){
return p[i];}
};void indexop :: read(int n){
for(int i=0;i<n;i++){
cout<<"Enter val\n";cin>>p[i];
}}
main(){
indexop iop1;int n;cout<<"enter n\n";cin>>n;iop1.read(n);for(int i=0;i<n;i++)cout<<iop1[i]<<"\t"; // call of [] operator
}
// Index operaor with reference
#include<iostream>using namespace std;int n;class indexop{
int p[10];public:indexop(){
}int &operator[](int i){
return p[i];
}void display(){
for(int i=0;i<n;i++)cout<<p[i]<<"\t";
}};
main(){
indexop iop1;cout<<"enter n\n";cin>>n;for(int i=0;i<n;i++){
int v;cout<<"enter v\n";cin>>v;iop1[i]=v;
}iop1.display();
}
2. Overloading () (function call operator)
Example program:
#include<iostream>using namespace std;class marksclass{
int regdno;float marks;public:marksclass(int r,float m){
cout<<"Constructor is called\n";regdno=r;marks=m;
}marksclass operator()(int r,float m){
cout<<"Operator function is called \n";regdno=r;
marks=m;return *this;
}void display(){
cout<<"Regdno "<<regdno<<" got "<<marks<<"\n";}
};main(){
marksclass stumarks(1001,67);stumarks.display();stumarks(1205,86); // this is the function call () operator callstumarks.display();
}
3. Overloading ->
The –> pointer operator, also called the class member access operator, is considereda unary operator when overloading. Its general usage is shown here:
object->element Here, object is the object that activates the call. The operator–>( ) function must
return a pointer to an object of the class that operator–>( ) operates upon. The element must be some member accessible within the object.
Example:
#include <iostream>using namespace std;class myclass{int a,b,sum;public:void read(){cout<<"\n enter numbers";cin>>a>>b;}void total(){sum=a+b;}void show(){cout<<"sum="<<sum;
}myclass *operator->() {return this;}};int main(){myclass ob;ob->read();ob->total();ob->show();return 0;}
4. Overloading the comma operator
The comma is a binary operator. The rightmost value becomes the result of the comma operation.
Example program from notes or
#include <iostream>using namespace std;class loc {int longitude, latitude;public:loc() {}loc(int lg, int lt) {longitude = lg;latitude = lt;}void show() {cout << longitude << " ";cout << latitude << "\n";}loc operator+(loc op2);
loc operator,(loc op2);};// overload comma for locloc loc::operator,(loc op2){loc temp;temp.longitude = op2.longitude;temp.latitude = op2.latitude;cout << op2.longitude << " " << op2.latitude << "\n";return temp;
}// Overload + for locloc loc::operator+(loc op2){loc temp;temp.longitude = op2.longitude + longitude;temp.latitude = op2.latitude + latitude;return temp;}int main(){loc ob1(10, 20), ob2( 5, 30), ob3(1, 1);ob1.show();ob2.show();ob3.show();cout << "\n";ob1 = (ob1, ob2+ob2, ob3);ob1.show(); // displays 1 1, the value of ob3return 0;}