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

Chapter6 PDF

Operator overloading allows operators to be used with user-defined types in C++. It allows operators to have special meanings for specific data types. Common operators like + and ++ can be overloaded so that they perform type-appropriate operations when used with class objects. Overloaded operators are implemented with special operator functions that describe the task to be performed. Operator overloading contributes to C++'s extensibility and allows code to be clearer compared to explicit function calls.

Uploaded by

Rosʜʌŋ
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
35 views

Chapter6 PDF

Operator overloading allows operators to be used with user-defined types in C++. It allows operators to have special meanings for specific data types. Common operators like + and ++ can be overloaded so that they perform type-appropriate operations when used with class objects. Overloaded operators are implemented with special operator functions that describe the task to be performed. Operator overloading contributes to C++'s extensibility and allows code to be clearer compared to explicit function calls.

Uploaded by

Rosʜʌŋ
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 14

Chapter 6

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.

Defining operator overloading:


An operator overloading is defined with the help of a special function, called operator
function, which describes the task to be done by the operator. The syntax for operator
function is:
return_type operator op(arguments);
where operator is keyword and op may be any valid operator to be
overloaded. Thus, operator op is function name.
Operator function may be either member function or friend function. A friend
function will have only one argument for unary operators and two for binary operators
while member function has no argument for unary and one for binary operators. The
member function takes one less argument because, here, the object used to invoke the
member function is passed implicitly and therefore available for the member function.

Invocation of overloaded operator:


a) Unary operator
Overloaded operator function is invoked using expression
op x or x op

Prepared By: Er. Dipesh Bista


This is interpreted as

i) For operator Function as member Function: x.operator op()


ii) For operator Function as friend Function: operator op(x)
b) Binary operator
Overloaded binary operator function is invoked using expression
x op y
This is interpreted as

i) For operator Function as member Function: x.operator op(y)


ii) For operator Function as friend Function: operator op(x,y)

Operator Overloading Restrictions


• Only those operators that are predefined in the C++ compiler can be used. User
cannot create new operators such as $, @, etc.
• The overloaded operator must have at least one operand that is of used defined type.
• The original meaning of overloaded operator is not changed.
• Overloaded operators follow the syntax rules of the original operators. They cannot
be overridden.
• The operators sizeOf, :: (scope resolution), ?: (conditional) and .*(pointer to
member) operator can be overloaded.
• Friend function can not be used to overload operators =,(), [] and ->.
• Binary operators overloaded through a member function take one explicit argument
and those which are overloaded through a friend function take two explicit
arguments.
• When using binary operators overloaded through a member function, the left hand
operand must be an object of the relevant class.

Overloading Binary Operators:


An example: overloading of unary minus operator (i.e. -)
#include <iostream.h>
#include <conio.h>
class opTest
{
int x,y,z;
public:
opTest(int a, int b, int c)
{ x=a; y=b; z=c; }
void display(void)
{ cout<<x<<" "<<y<<" "<<z<<"\n"; } Output of the program:
void operator-() The original object is: 10 -20 30
{ x=-x; y=-y; z=-z; } The -ve of the object: -10 20 -30
};

void main()
{

Prepared By: Er. Dipesh Bista


opTest ob(10,-20,30);
cout<<"The original object is: ";
ob.display();
-ob; //activates operator -() function
cout<<"The -ve of the object: ";
ob.display();
}

Example2: overloading of increment operator i.e. (++)


class counter
{
unsigned int count; Output of the above program
public: C1=0
counter() //Constructor C2=0
{ count=0; } C1=1
int getcount() //return count C2=2
{ return count; } Note: The ++ operator is applied
void operator ++() //increment (prefix) once c1 and twice to c2.
{ ++count; }
};
void main()
{
counter c1,c2; //define and initialization
cout<<"\nC1= "<<c1.getcount(); //display
cout<<"\nC2= "<<c2.getcount(); //display
++c1; //c1.operator++(), incremant c1
++c2; //incremant c2
++c2; //incremant c2
cout<<"\nC1= "<<c1.getcount(); //display again
cout<<"\nC2= "<<c2.getcount(); //display again
getch();
}

Example3: Program to use increment counter variable with ++ operator using


postfix and prefix notation
class counter
{
unsigned int count;
public:
counter() //Constructor no argument
{ count=0; }
int getcount() //return count
{ return count; }
counter operator ++() //increment (prefix ++c1)
{ counter temp;
temp.count=++count;

Prepared By: Er. Dipesh Bista


return temp; }
counter operator ++(int) //increment (postfix c1++)
{ counter temp;
temp.count= count++;
return temp; }
};

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.

Binary Operator Overloading:


Example1: Arithmetic operator (+) overloading for addition of two complex
numbers
class complex
{
private:
float x, y;
public:
complex() { } // constructor1 without argument
complex (float real, float imag) //constructor2 declared with two arguments
{ x=real;
y=imag;
}
complex operator+ (complex); //declaration of operator function
void show(void)
{ cout<<x<<" + j "<<y<<endl; }
};

complex complex::operator+(complex c)
{ complex temp;
temp.x=x+c.x;
temp.y=y+c.y;

Prepared By: Er. Dipesh Bista


return (temp); // or simply return complex(x+c.x, 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.

Example2: Overloading of plus operator to concatenation of two strings


#include<string.h>
class string
{ private:
char st[30];
public:
string()
{ strcpy(st,""); }
string(char input[])
{ strcpy(st,input); }
void display()
{cout<<st;}
string operator+(string secString)
{
string temp;
strcpy(temp.st, st);
strcat(temp.st, secString.st);

Prepared By: Er. Dipesh Bista


return temp;
}
};

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();
}

Example3: overloading of less than relational operator (i.e. <).


enum boolean{false, true};
class distance
{ private:
int feet, inch;
public:
distance() Output of the program:
{ feet=0;inch=0; } First Run:
distance(int f, int i) Enter feet 3
{ feet=f; inch=i; } Enter inches 5
void display() Enter feet 7
{cout<<feet<<"\'"<<inch<<'\"';} Enter inches 9
void getDist()
{ cout<<"Enter feet";cin>>feet; Distance1=3'5"
cout<<"Enter inches";cin>>inch; } Distance2=7'9"
boolean operator<(distance d2) Distance1 is less than distance2
{ float f1=feet+(inch/12);
Second Run:
float f2=d2.feet+(d2.inch/12); Enter feet 9
return((f1<f2)?true:false);} Enter inches 0
}; Enter feet 6
Enter inches 9
void main()
{ distance d1,d2; Distance1=9'0"
d1.getDist(); Distance2=6'9"
d2.getDist(); Distance1 is more than distance2
cout<<"\nDistance1=";d1.display();
cout<<"\nDistance2=";d2.display();
if(d1<d2)

Prepared By: Er. Dipesh Bista


cout<<"\nDistance1 is less than distance2";
else
cout<<"\nDistance1 is more than distance2";
}

Operator overloading Using friend Function:


Friend function may be used in the place of member function for overloading operator.
The only difference is that a friend function requires one argument for unary operator and
two for binary to be explicitly passed to it. There are certain situations where we would
like to use a friend function rather than a member function. In the overloading of binary
operator using member function, the left-hand operand is used to invoke the operator
function and the right-hand operand is passed as an argument. Thus, the member function
can not be used when there are two different operands for binary operators, say, first
operand is a built –in data type and other is object. For example
A=2+B
Where A and B are objects and 2 is an integer constant. In this situation, friend
function rather than member function is used.
Examle1: overloading unary minus operator using friend function
class opTest
{
int x,y,z;
public:
opTest()
{}
opTest(int a, int b, int c)
{ x=a; y=b; z=c; }
void display(void)
{ cout<<x<<" "<<y<<" "<<z<<"\n"; }
friend opTest operator-(opTest);
};

opTest operator-(opTest obj)


{ return opTest(-obj.x,-obj.y,-obj.z);} //name less temporary object

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.

Prepared By: Er. Dipesh Bista


class complex
{
private:
float x,y;
public:
complex()
{ }
complex (float real, float imag) //constructor2 declared with two arguments
{ x=real;
y=imag; }
friend complex operator+ (complex,complex); //declaration of operator function
void show(void)
{
cout<<x<<" + j "<<y<<endl;
}
}; Output of the program:
complex operator+(complex c1, complex c2) C1=3 + j 2
{ complex temp; C2=4 + j 1
temp.x=c1.x+c2.x; C3=7 + j 3
temp.y=c1.y+c2.y;
return (temp); // or simply return complex(x+c.x, y+c.y)
}

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();
}

Example3: Overloading of multiplication operator (i.e. *) to multiply each element


of a matrix by certain integer.
class matrix
{
private:
int m[2][2];
public:
void getMatrix();
void display();
friend matrix operator *(int, matrix);
};

Prepared By: Er. Dipesh Bista


void matrix::getMatrix()
{ cout<<"Enter matrix:\n" ;
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
cin>>m[i][j];
}
void matrix::display()
{
cout<<"\nThe matrix is:\n" ;
for(int i=0;i<2;i++)
{
for(int j=0;j<2;j++)
cout<<"\t"<<m[i][j];
cout<<"\n";
}
}
matrix operator *(int factor, matrix m1)
Output of the program:
{ matrix temp;
Enter matrix:
for(int i=0;i<2;i++) 3 4 5 6
for(int j=0;j<2;j++)
temp.m[i][j]=m1.m[i][j]*factor; The matrix is:
return temp; 3 4
} 5 6
void main()
{ The matrix is:
matrix mat,ResMatrix; 9 12
mat.getMatrix(); 15 18
mat.display();
ResMatrix=3*mat;
ResMatrix.display();
}

Data Conversion

Conversion between Basic Types:


See standard conversions in chapter 2 for this.

Conversion between objects and Basic Types:


a) Conversion From Basic to User defined data type:
A constructor can be used to covert basic data type to user defined data type. It
may be important to know that an object can be initialized using one argument
constructor as
Square s(10); Å---Æ Square s=10; // Assume that Square is class name
and it has one constructor Square(int).

Prepared By: Er. Dipesh Bista


An example:
const float MTF=3.280833;
class distance
{
int feet;
float inches;
public:
distance() //constructor
{ feet=0; inches=0.0; }

distance(float meters) //constructor with one argument


{ float floatfeet= MTF * meters;
feet=int(floatfeet);
inches=12*(floatfeet-feet); }

void showdist() //display distances


{ cout<<feet<<"\' - "<<inches<<'\"'; }
};

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();
}

b) Conversion From User defined to Basic data type:


C++ allows us to define an overloaded casting operator that could be used to
covert a class type data to a basic type. Syntax for an overloaded casting
operator function is:
operator type_name()
{……….. }
This function converts a class type (of which it is member) data to type_name.
The casting operator function should satisfy following conditions.
¾ It must be a class member
¾ It must not specify a return type
¾ It must not have any arguments

Prepared By: Er. Dipesh Bista


An example:
const float MTF=3.280833; //meter to feet
class distance
{
int feet;
float inches;
public:
distance() //constructor
{ feet=0; inches=0.0; }

distance(int ft, float in) //constructor with two arguments


{ feet=ft;
inches=in; }

operator float() //conversion function


{ float fracfeet=inches/12; Output of the program:
fracfeet+=float(feet); Dist1 = 1 meters
return (fracfeet/MTF); Dist2=1.666244meters
}
};

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";
}

Conversion between objects of Different Classes

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.

Routine in source object


When the conversion routine is in the source class, it is commonly accomplished using a
conversion function. The two classes used in the next program are rectangular and polar
class. The rectangular class is similar in that its objects are points in a two dimensional
plane. However, it uses a rectangular coordinate system, where the location of each point

Prepared By: Er. Dipesh Bista


is specified by x and y coordinates. Its member functions are similar to those for polar but
are adapted to rectangular coordinates.
An example:
#include <math.h>
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; }
void display()
{ cout<<"(" <<xco<<","<<yco<<")"; }
};

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();
}

Prepared By: Er. Dipesh Bista


Routine in destination object
When the conversion routine is in the destination class, we use a one-argument
constructor. However, things are complicated by the fact that the constructor in the
destination class must be able to access the data in source class to perform the
conversion. The polar data – radius & angle –are private, so we must provide special
function to allow direct access it.

#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);

Prepared By: Er. Dipesh Bista


yco=a * sin(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();
}

Prepared By: Er. Dipesh Bista

You might also like