Chapter6 PDF
Chapter6 PDF
Operator Overloading
Introduction:
Operator overloading is one of the many exciting features of C++ language. C++ tries to
make the user-defined data types behave in much the same way as the built in types. For
instance, C++ permits us to add two variables of user-defined types with the same syntax
that is applied to the basic types. This means that C++ has the ability to provide the
operator with a special meaning for a data type. The mechanism of giving such special
meanings to an operator is known as operator overloading.
Programmers can use operators with user-defined types as well. Normally,
a=b+c; works only with basic data types like int and float. However, using
operator overloading, we can make this statement legal for user-defined data type also
(like object). The use + operator for two objects, means giving special meaning to +
operator. The statement like C3.add_complex(C1,C2) can be converted into statement
like C3=C1+C2 using operator overloading.
Although C++ does not allow new operators to create, it does allow most
existing operators to be overloaded so that when these operators are used with class
objects, the operators have meaning appropriate to the new type. This is one of the C++
’s most powerful features. Operator overloading contributes to C++ ’s extensibility, one
of the language’s most appealing attributes. Operator overloading is used when it makes a
program clearer than accomplishing the same operations with explicit function calls.
Excessive or inconsistent use of operator overloading is avoided as this can make a
program cryptic and difficult to read. An operator is overloaded to perform the same
function or similar function on class objects as the operators perform on objects of built
in types.
The main advantage of the operator overloading process in a program is that it
much easier to read and debug.
void main()
{
void main()
{ Output of the program
counter c1,c2; //define and initialization C1=0
cout<<"\nC1= "<<c1.getcount(); //display C2=0
cout<<"\nC2= "<<c2.getcount(); //display C1=3
++c1; //incremant c1=1 C2=2
c1++; //postfix c1=2
c2=c1++; //incremant c1=3,c2=2
cout<<"\nC1= "<<c1.getcount(); //display again
cout<<"\nC2= "<<c2.getcount(); //display again
}
Here, the member function for postfix function is similar to that of prefix, except that, by
convention, it takes a single argument of type int in declaration i.e. counter operator
++(int). This int is not really an argument, but a signal to the compiler that we want to
use postfix notation.
complex complex::operator+(complex c)
{ complex temp;
temp.x=x+c.x;
temp.y=y+c.y;
int main()
{ Output of the program
complex C1,C2,C3; //Invoke Constructor1 C1=2 + j 4
C1=complex(2,4); //invoke Constructor2 C2=4 + j 6
C2=complex(4,6); C3=6 + j 10
C3=C1+C2; // equivalent to C1.operator+(C2)
cout<<"C1=";C1.show();
cout<<"C2=";C2.show();
cout<<"C3=";C3.show();
}
In the above program, function receives only one complex type argument explicitly. It
returns a complex type value, and it is a member function of class complex. In the
overloading of binary operator, the left-hand operand is used to invoke the operator
function and the right-hand operand is passed as an argument. Thus, C3=C1+C2 is
equivalent to C3=C1.operator+(C2).
Temporary Objects:
We can avoid the creation of the temp object by replacing the entire function body
in declaration of complex::operator+(complex c) operator function by the following
statement: return complex(x+c.x, y+c.y).
When a compiler comes across a statement invokes the constructor2, initializes an
object with no name and returns the contents for copying into an object. Such an object is
called temporary object and goes out of space as soon as the contents are assigned to
another object. Using temporary objects can make the code shorter, more efficient and
better to read.
void main()
{
string S1("WelCome"); Output of the program:
string S2(" To This College"); S1=WelCome
S2= To This College
string S3;
S3=WelCome To This College
clrscr();
S3=S1+S2;
cout<<"S1="; S1.display();
cout<<"\nS2="; S2.display();
cout<<"\nS3="; S3.display();
getch();
}
void main()
{
opTest ob(10,-20,80),obN;
cout<<"The original object is: ";
ob.display();
obN= -ob; // is same as operator-(ob); Output of the program:
cout<<"The -ve of the object: "; The original object is: 10 -20 80
The -ve of the object: -10 20 -80
obN.display();
}
Example2: Overloading of plus operator to add two complex numbers using friend
function.
void main()
{
complex C1,C2,C3; //Invoke Constructor1
C1=complex(3,2); //invoke Constructor2
C2=complex(4,1);
C3=C1+C2; //same as opeator+(C1,C2)
cout<<"C1=";C1.show();
cout<<"C2=";C2.show();
cout<<"C3=";C3.show();
}
Data Conversion
void main()
{
distance dist1=1.144,dist2; // uses 1 argument constructor to
//convert meter to distance
//same as dist1(1.144)
dist2=3.5; // uses 1 argument constructor i.e. same as dist2(3.5).
clrscr();
cout<<"\nDist1 = "; Output of the program:
dist1.showdist(); Dist1 = 3' - 9.039279"
cout<<"\nDist2 = "; Dist2 = 11' - 5.794991"
dist2.showdist();
getch();
}
void main()
{
distance dist1(3,3.37), dist2(5,5.6);
float mtrs=float(dist1); /*Uses conversion function to convert
distance to meter & equivalent to dist1.operator float()*/
cout<<"\nDist1 = "<<mtrs<<" meters";
mtrs=dist2; // dist2.operator float();
cout<<"\nDist2="<<mtrs<<"meters";
}
The same two methods as same as conversion between basic types and user-defined types
also apply to conversions between two user-defined types. That is, you can use a one-
argument constructor, or you can use a conversion function. The choice depends on
whether you want to put the conversion routine in the class specifier of the source object
or of the destination object.
class polar
{
double radius,angle; //x and y cordinate
public:
polar() //constructor
{ radius=0.0; angle=0.0; }
polar(double r, double a)
{ radius=r; angle=a; }
void display()
{ cout<<"(" <<radius<<","<<angle<<")"; }
operator rectangular() //casting operator function
{ double x=radius * cos(angle);
double y=radius * sin(angle);
return rectangular(x,y); } //temporary object
};
void main() Output of the program
{ Polar Values=(10,0.785398)
rectangular rec; Rec Values=(7.071069,7.071067)
polar pol(10.0,0.785398);
rec=pol; //or rec=rectangular(pol);
// It is equivalent to pol.operator rectangular()
cout<<"\nPolar Values=";
pol.display();
cout<<"\nRec Values=";
rec.display();
}
#include<iostream.h>
#include<conio.h>
#include <math.h>
class polar
{
double radius,angle; //x and y cordinate
public:
polar() //constructor
{ radius=0.0;
angle=0.0; }
polar(double r, double a)
{ radius=r; angle=a; }
void display()
{ cout<<"(" <<radius<<","<<angle<<")"; }
double getr()
{ return radius; }
double geta()
{ return angle; }
};
class rectangular
{
double xco,yco; //x and y cordinate
public:
rectangular() //constructor
{ xco=0.0; yco=0.0; }
rectangular(double x, double y)
{ xco=x; yco=y; }
rectangular (polar p)
{
double r=p.getr();
double a=p.geta();
xco=r * cos(a);
void display()
{ cout<<"(" <<xco<<","<<yco<<")"; }
};
void main()
{
rectangular rec; //rectangular using constructor1
polar pol(10.0,0.785398); //polar using constructor1
rec=pol; //convert polar to rectangular using conversion function
clrscr();
cout<<"\nPolar Values=";
pol.display(); Output of the program
cout<<"\nrectangular Values="; Polar Values=(10,0.785398)
rec.display(); Rec Values=(7.071069,0.55536)
getch();
}