Вы находитесь на странице: 1из 58

OPERATOR

OVERLOADING
Satyendra Singh Chouhan
Assistant professor (CSE)
8/21/2017 2

Operator overloading
• With objects, an operator, like “+”, is really just a function
with a different syntax
• With a binary operator, the arguments are placed on
either side of the operator
string air = "air", plane = "plane";
string combined = air + plane;

lhs operator rhs

• The compiler generates the following function call


string combined = operator+( air, plane );

lhs rhs
8/21/2017 3

Operator overloading
• Just like any function, operators can be overloaded

• Operators are already overloaded so that they “do the


right thing” with all built-in data types, like int and double
42 + 58;
98.6 + 0.3;

• Also with classes in the standard library, like string


string result;
result = result + "test";

• But operators are not automatically overloaded for


classes that we create (User define classes)
8/21/2017 4

Operator overloading
• We have to overload operators for the classes that we create

• The implementation of an overloaded operator is usually a


member function of the class of the object used on the lhs
• Example of a binary operator used with objects of a class we made
Book book1, book2; //Instantiate two book objects
Book book3 = book1 + book2;

lhs operator rhs


• The operator + must be implemented as a public member function
class Book lhs
{ rhs
public:
Book& operator+( const Book& rhs );
//remainder of the code left out...
};
8/21/2017 5

Operator overloading
Restrictions
• Precedence of operators cannot be changed

• Arity of operators cannot be changed (“arity” is the


number of operands)
• New operators cannot be created

• Operators for built-in data types cannot be overloaded

• Some operators cannot be overloaded


Defining Operator Overloading
• Defining Additional task to an operator.
• General form
return_type class_name::operator op(arglist)
{
function body
}

Op is the operator being overloaded like +,-,<< etc.


Op is preceded by the keyword operator.
Operator Overloading (Cont…)
• operator functions must be either member functions or
friend functions.
• Differences between using friend function and member
function.
• Friend function will have only one argument for unary operator and
two argument for binary operators.
• Member function will have no arguments for unary operators and
only one argument for binary operators.
• The object used to invoke the member function is passed implicitly to
the function and this is not the case with friend function.
Operator Overloading (Cont…)
• Overloaded operator can be invoked like:
• Unary Operator:
i. Op obj ; this would be interpreted as operator op (obj)
ii. -obj ; this would be interpreted as operator - (obj)
iii. +obj etc
Binary Operator:
i. ob1 op ob2; this would be interpreted as ob1.operator
op (ob2) in case of member function
And operator op(ob1,ob2) in case of friend function
Overloading unary operator
A minus operator when used as a unary, takes just one
operator.
#include<iostream>
using namespace std;
class space
{
int x;
int y;
int z;
public:
void set_data(int a, int b,int c);
void display(void);
void operator-(); //overloading unary minus
};
Defining all member functions
void space::set_data(int a,int b,int c)
{
x=a; y=b; z=c;
}
void space::display(void)
{cout<<x<<“ ”<<y<<“ ”<<z<<“\n”;}

void space:: operator-()


{ x=-x;
y=-y;
z=-z;
}
Defining main() function
int main()
{
space s;
s.set_data(10,-20,30);
cout<<“S:=”;
s.display();
-s; //compiler see this statement like s.operator-
();
cout<<“-S:=“;
s.display();
return 0;
}
Output

S: = 10 -20 30
-S: = -10 20 -30
Overloading unary operator using friend
function
#include<iostream>
using namespace std;
class space
{
int x;
int y;
int z;
public:
void set_data(int a, int b,int c);
void display(void);
friend void operator-(space &s);//overloading unary
minus
};
Defining all member functions
void space::set_data(int a,int b,int c)
{
x=a; y=b; z=c;
}
void space::display(void)
{cout<<x<<“ ”<<y<<“ ”<<z<<“\n”;}

void operator-(space &s)


{ s.x=-s.x;
s.y=-s.y;
s.z=-s.z;
}
Defining main() function
int main()
{
space s;
s.set_data(10,-20,30);
cout<<“S:=”;
s.display();
-s; //compiler see this statement like operator-
(s);
cout<<“-S:=“;
s.display();
return 0;
}
Overloading binary operators
• Binary operator can be overloaded in similar fashion as the
unary operator.
#include<iostream>
using namespace std;
class complex
{
float x;
float y;
public:
complex(){} //Constructor 1
complex(float real, float imag) // Constructor 2
{ x=real; y= imag;}
complex operator+(complex); //Overloading + operator
void display(void);
};
Overloading binary operators(cont…)
complex complex::operator +(complex c)
{
complex temp;
temp.x=x+c.x;
temp.y=y+c.y;
return (temp);
}
void complex:: display(void)
{
cout<<x<<“+j”<<y<<“\n”;
}
Main() function
int main()
{
complex c1(2.5,3.5); //invokes constructor 2
complex c2(1.6,2.7); //invokes constructor 2
complex c3; //invokes constructor 1
c3=c1+c2; //complier see like this c3=c1.operator+(c2);
cout<<“c1 =“; c1.display();
cout<<“c2=“; c2.display();
cout<<“c3=“;c3.display();
return 0; O/P
c1=2.5+j3.5
} c2=1.6+j2.7
c2=4.1+j6.2
8/21/2017 19

Nameless Temporary Objects


Re-look this defintion
complex complex::operator +(complex c)
{
complex temp;
temp.x=x+c.x;
temp.y=y+c.y;
return (temp);
}
• Here temp object is created , whose sole purpose was to provide a
return value for the + operator. This required four statements.
• Same definition with one statement
complex complex::operator +(complex c)
{
return (complex(x+c.x, y+c.y));// here constructor 2 will create
// temporary object without name
}
Overloading binary operators using friend
function
#include<iostream>
using namespace std;
class complex
{
float x;
float y;
public:
complex(){} //Constructor 1
complex(float real, float imag) // Constructor 2
{ x=real; y= imag;}
friend complex operator+(complex,complex);
void display(void);
};
Overloading binary operators using
friend function (Cont…)
complex operator +(complex c1, complex c2)
{
complex temp;
temp.x=c1.x+c2.x;
temp.y=c1.y+c2.y;
return (temp);
}
void complex:: display(void)
{
cout<<x<<“+j”<<y<<“\n”;
}
Overloading binary operators using friend
function (Cont…)
int main()
{
complex c1(2.5,3.5); //invokes constructor 2
complex c2(1.6,2.7); //invokes constructor 2
complex c3; //invokes constructor 1
c3=c1+c2; //complier see like this c3=operator+(c1,c2);
cout<<“c1 =“; c1.display();
cout<<“c2=“; c2.display();
cout<<“c3=“;c3.display();
return 0; O/P
c1=2.5+j3.5
} c2=1.6+j2.7
c2=4.1+j6.2
23

Sample Class in Book.h


#ifndef BOOK_H
#define BOOK_H
#include <string>
using std::string;

class Book{
public:
Book( string t="",int cpy=0 ): title(t), copies(cpy){}
void setTitle( string t ){ title = t; }
string getTitle(){ return title; }
void setCopies ( int cpy ){ copies = cpy; }
int getCopies(){ return copies; }
string toString(){ return "Book: " + title; }
private:
string title;
int copies;
};
#endif
24

Binary Operators
• Operands are placed on both sides of the operators
• Example: the equality operator
• Usage
Book book1("C++ How to Program",1);
Book book2("Java How to Program",1);
if( book1 == book3 ) cout << "Equal" << endl;

lhs operator rhs


• Implementation
class Book{
public:
bool operator==( const Book& rhs ){
return this->title==rhs.title;
}
lhs
25

Unary Operators
• Only one operand
• Example: the not operator
• Usage
Book book3;
if( !book3 ) cout << "empty" << endl;

lhs
• Implementation
class Book{
public:
bool operator!(){
return ( title=="" && copies==0 );
}
The conditions of an “empty” object
26

Stream Insertion Operator

• The stream insertion operator is a binary operator


• Usage
cout << "Hello";

lhs operator rhs

• The lhs is a C++ object of the ostream class which is in


the iostream library
• The ostream class knows how to output any of the built-in
C++ data types and any standard library data types
• We have to overload << for our own classes, but we can’t
put the overloaded operator into the lhs class
27

Stream Insertion Operator


• We implement << as a global function and then declare it
as a friend of our own class
• Example:
• Usage
cout << book1;

• Implementation
class Book{
friend ostream& operator<<( ostream& out, const Book& rhs );
//remainder of the Book class here
};
lhs rhs
Global function definition:
ostream& operator<<( ostream& out, const Book& rhs ){
out << rhs.title;
A friend has access to the
return out; private data members
}
28

Stream Extraction Operator

• Implement as a friend function


• Example:
• Usage
cin >> book3; //Already declared like this: Book book3;

• Implementation
class Book{
friend istream& operator>>( istream& in, Book& rhs );
//remainder of the Book class here
};
Global function definition:
istream& operator>>( istream& in, Book& rhs ){
in >> rhs.title;//captures a single word, no whitespace
in >> rhs.copies;
return in;
}
29

Overloading ++
• Special syntax to distinguish pre- from post-increment
• Example:
• Usage
book1++;
cout << "Copies = " << book1.getCopies() << endl;

• Implementation as member functions of the Book class


Book& operator++(){ //Pre-increment
++copies;
return *this;
}
Book operator++(int){ //Post-increment
Book temp = *this;
++copies;
return temp;
}
8/21/2017 30

• Q.If we get same result in operator


overloading by the use of either a friend
function or a member function. Why then
alternative is made available?
Ans:
Consider a situation where we need one buit-in
type operand and one object.
• A=B+2; will work for both cases friend function and member
function
• A=2+B;will generate syntax error for member function but
works correctly for friend function (Why?)
Rules for overloading operators
• Only existing operator can be overloaded
• New operators cannot be created.
• Overloaded operator should have at least one operand of
user defined data type.
• We cannot change the basic meaning of the operator.
• overloaded operators follow the syntax rules of the original
operators.
Operators that cannot be overloaded

Sizeof size of operator


. Membership operator
.* pointer to member operator
:: scope resolution operator
?: conditional operator
8/21/2017 33

Identify the error


#include <iostream>
using namespace std;
class Space
{
public:

int mCount;
Space()
{
mCount = 10;
} int main()
{
Space operator ++() Space objSpace;
{ ++ objSpace;
mCount++; cout<<++objSpace.mCount;
return Space(mCount); return 0;
} }
};
Type Conversions
int m ;
float x=3.14159;
m = x; //compiler converts x to an integer before its
assignment
Consider this: obj=obj1+obj2;// where obj,obj1and obj2 are
object of same class
• The assignments between basic types or user defined
types are taken care by the compiler provided the data
type on both sides of = are of same type.
• But what to do in case the variables are of different types
on both sides of the = operator? In this case we need to
tell to the compiler for the solution.
• Ex.obj=20;
8/21/2017 35

Type Conversions (cont…)


Three types of situations might arise in the data
conversion between incompatible types:
1. Conversion from basic type to class type.
2. Conversion from class type to basic type.
3. Conversion from one class type to another
class type.
Basic to Class Type
class time
{
int hrs,mins;
public:
time(){}
time(int t)
{hrs=t/60;
mins=t%60;
}
};
8/21/2017 37

Basic to Class Type (cont…)


• If there are statements like as shown below
Time t1,t2; //object t1 and t2 are created
int duration1=70,duration2=85;
t1=time(duration1);//explicit call
t2=duration2; //(implicit call) converting int to class type

• Constructor converts duration from int to class type and then assigns
the time type to the values of the object time
• After conversion, the hrs member of t2 will contain a value of 1 and
mins member a value of 25.
8/21/2017 38

Exercise
Write c++ program which has class distance containing
data members feet and inches . also write the necessary
type conversion code to allow following statement in main
function.
distance dist1; //object dist1 created
int length = 20;
dist1=length; //int to class type

Sample output:
feet=1 and inches=8
Class to Basic Type
• Constructor cant do this type of conversion.
• C++ allow us to define overloaded casting(conversion )
operator that is used to convert a class type data to a
basic data type.
• General form:
operator typename()
{
function statements
}
This function converts a class type data to typename.
Eg. operator int() converts a class object to type int
operator double() converts a class object to type
double
Eg for overloaded casting operator
vector :: operator double()
{
double sum=0;
for(int i=0; i<size; i++)
sum=sum + v[i] * v[i];
return sqrt(sum);
}
• The function converts a vector to the corresponding
scalar magnitude.
• The magnitude of a vector is given by square root of
the sum of the squares of its components.
double length=double(v1); or
double length=v1; // When a class type to a basic type conversion is
required, the compiler will call the casting operator function for
performing this task
Casting operator function
• Casting operator function should satisfy the following
conditions:
• It must be a class member.
• It must not specify a return type.
• It must not have any arguments.
One class to another class
For example,
studdata obj1;
result obj2;
• obj2 = obj1; //different type of objects
• We are converting the class studdata data type to class result type
data and the value is assigned to obj2.
• Here studdata is known as source class and result is known as the
destination class.
• The above conversion can be performed in two ways :
(a) Using a constructor.
(b) Using a conversion function.
One class to another class
• If we take a single-argument constructor function for
converting the argument’s type to the class type (whose
member it is). So the argument is of the source class and
being passed to the destination class for the purpose of
conversion. Therefore it is compulsory that the conversion
constructor be kept in the destination class.
• Example:
• Constructor function to be placed in destination class.
class X
{
public:
X(Y obj_y)
{
}
One class to another class(cont…)
• When we need to convert a class, a casting operator
function can be used i.e. source class. The source class
performs the conversion and result is given to the object of
destination class.
Example:
class Y
{
public:
operator X();
};
Y::operator X()
{
// definition
}
8/21/2017 45

• /* Program converts from one class type to * another using a conversion


function * and a constructor */
#include <iostream>
using namespace std;
class Kilometers{
private: double kilometers;
public:
Kilometers(double kilometers): kilometers(kilometers) {}
void display() {
cout << kilometers << " kilometeres"; }
double getValue()
{ return kilometers; }
};
8/21/2017 46

class Miles{
private: double miles;
public:
Miles(double miles) : miles(miles) {}
void display() { cout << miles << " miles";
}
operator Kilometers() {
return Kilometers(miles*1.609344); }
Miles(Kilometers kilometers)
{
miles = kilometers.getValue()/1.609344;
}
};
8/21/2017 47

int main(void){
/* * Converting using the conversion function */
Miles m1 = 100;
Kilometers k1 = m1;
m1.display(); cout << " = ";
k1.display(); cout << endl; /* Converting using the constructor */
Kilometers k2 = 100;
Miles m2 = k2; // same as: Miles m2 = Miles(k2);
k2.display();
cout << " = ";
m2.display();
cout << endl;
}
8/21/2017 48

O/P
• 100 miles = 160.934 kilometeres
• 100 kilometeres = 62.1371 miles
8/21/2017 49

Conversions: When to Use What


• When should you use the one-argument constructor in the
destination class, as opposed to the conversion operator
in the source class? Mostly you can take your pick.
• However, sometimes the choice is made for you. If you
have purchased a library of classes, you may not have
access to their source code. If you use an object of such a
class as the source in a conversion, you’ll have access
only to the destination class, and you’ll need to use a one-
argument constructor.
• If the library class object is the destination, you must use a
conversion operator in the source.
8/21/2017 50

Problem:Overload ++
• How to differentiate overloading of pre-increment and post-increment
operators?
• To make both versions of the increment operator work, we define two
overloaded ++ operators,
• For overloading pre-increment ++, usual way of unary operator will be
followed.
• Eg. Returnt_type operator++()
• For overloading post-increment C++ developer used concept of dummy
parameter
• Eg. Return_type operator++(int)
• Note: The only difference is the int in the parentheses. This int isn’t
really an argument, and it doesn’t mean integer. It’s simply a signal to
the compiler to create the postfix version of the operator
8/21/2017 51

Cont…
// overloaded ++ operator in both prefix and postfix
#include <iostream>
using namespace std;
class Counter
{ private:
int count; //count
public:
Counter() : count(0) //constructor no args
{}
Counter(int c) : count(c) //constructor, one arg
{}
8/21/2017 52

Cont…
int get_count() const //return count
{
return count;
}
Counter operator ++ () //increment count (prefix)
{
return Counter(++count); //an unnamed temporary object
}
Counter operator ++ (int) //increment count (postfix)
{
return Counter(count++); / /return an unnamed temporary object initialized to
} this count, then increment count
};
8/21/2017 53

Cont…
int main()
{
Counter c1, c2; //c1=0, c2=0
cout << “\nc1=” << c1.get_count(); //display
cout << “\nc2=” << c2.get_count();
++c1; //c1=1
c2 = ++c1; //c1=2, c2=2 (prefix)
cout << “\nc1=” << c1.get_count(); //display
cout << “\nc2=” << c2.get_count();
c2 = c1++; //c1=3, c2=2 (postfix)
cout << “\nc1=” << c1.get_count(); //display again
cout << “\nc2=” << c2.get_count() << endl;
return 0;
}
8/21/2017 54

Output:
c1=0
c2=0
c1=2
c2=2
c1=3
c2=2
8/21/2017 55

Exercise 1
Create a class RationalNumber (fractions) with the following
capabilities:
a.) Create a constructor that prevents a 0 denominator in a fraction,
reduces or simplifies fractions that are not in reduced form and avoids
negative denominators.
b.) Overload the addition, subtraction, multiplication and division
operators for this class.
c.) Overload the relational and equality operators for this class.

In addition to the capabilities outlined above, the RationalNumber


class should overload the stream insertion (<<) and stream extraction
(>>) operators. The stream extraction operator should prevent a 0
denominator in a fraction, reduce fractions that are not in reduced
form, and prevent negative denominators. Negative or 0
denominators should be set to 1.
8/21/2017 56

• Sample output 1
Enter a Rational Number (n/d): 1/3
Enter a Rational Number (n/d): 2/4
1/3 + 1/2 = 5/6
1/3 - 1/2 = -1/6
1/3 * 1/2 = 1/6
1/3 / 1/2 = 2/3
1/3 <= 1/2 according to the overloaded > operator
1/3 < 1/2 according to the overloaded >= operator
1/3 < 1/2 according to the overloaded < operator
1/3 <= 1/2 according to the overloaded <= operator
1/3 != 1/2 according to the overloaded == operator
1/3 != 1/2 according to the overloaded != operator
8/21/2017 57

Exercise 2
• Develop class Polynomial. This internal representation of
a polynomial is an array of terms. Each term contains a
coefficient and an exponent, hence you can have an array
for coefficients and exponents as a member of your
class(maximum number of terms will 100 however your
class should also contain a member variable that
indicates how many terms are there in a given instance of
the polynomial class).
Eg. the term 2x^4 has a coefficient of 2 and exponent of 4.
• Develop a full class containing proper constructor and
destructor functions as well as set and get functions.
8/21/2017 58

Exercise
• The class should also provide the following overloaded
operator capabilities:
1 overload the addition operator (+) to add two
polynomials.
2 overload the subtraction operator (-)to subtract two
polynomials
3 overload the assignment operator to assign one
polynomial to another
4 overload the multiplication operator(*) to multiply two
polynomials

Вам также может понравиться