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

Polymorphism function overloading and operator overloading

Uploaded by

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

Polymorphism function overloading and operator overloading

Uploaded by

ayushamber02
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 35

12.

2 Polymorphism
Polymorphism means something having multiple or
many forms. In C++ programming language, polymorphism is
also known as overloading. C++ allows to create multiple
functions of the same name and also give new meaning
to already defined operators.

12.3 Types of polymorphism


C++ broadly provides following types of polymorphism:

Figure 12.1 Polymorphism types

Compile Time Polymorphism:

In case of compile time polymorphism, C++ compiler is


provided enough information about the entities that helps the
compiler bind these entities to the respective statements used
to call these executions. Once the binding is done during
compile time, the same cannot be changed later on. Two
entities for which the compile time binding can be achieved in
C++ programming language are as follows:

Function Overloading- C++ programmers can create multiple


function definitions with the same function name and the
compiler is able to bind these definitions with respective
function call statements based on number of arguments or type
of function arguments.
Operator Overloading: It is a very powerful feature of C++. You
can overload the valid operator's used in C++ programming
language. In addition to their predefined meaning,
programmers can overload these operators and re-define them
for class objects.

Run time Polymorphism:

Run time polymorphism is also known as late binding.


Run time polymorphism is implemented with the help of
pointers. Binding of the entities is postponed during compile
phase and binding is done at run time. Virtual function is an
example or run time binding.

12.4 Function Overloading


Function overloading is compile time polymorphism or
overloading. It is also called function polymorphism. Function
overloading is used to create multiple functions of the
same name. Seems impossible but it is possible. The compiler
is able to differentiate between the multiple functions of the
same name and bind them to appropriate function call
statements. In this section, you will learn the methods using
which the function overloading can be achieved and how the
additional information is used by the compiler to differentiate
between the functions during compile time.

You can create one complete set of functions with the same
name that are capable of performing different operations.
These functions consists of different set of argument lists that
is used to differentiate between them and the kind of
operations they can perform also depends on the argument list
of each function.
Compiler is able to bind the function with appropriate function
call statement at the compile time using the number of
arguments in the argument list and the type of arguments.
Compiler in C++ programming language cannot differentiate
between the two functions with same name on the basic of
their return type.

Wherever a function call statement to an overloaded function is


encountered, the compiler first checks for the prototype of
function with the same number of arguments and same type. If
the compiler does not find any function prototype or more than
one function prototype that matches the function call
statement, it raises an error. For the first case, the error raised
is prototype for the function not found and for the second case,
the error raised is for ambiguity. It means that for every
function call statement, the compiler should be able to match it
with a unique prototype.

Once the compiler is able to find a unique match for the


function call statement in form of function prototype, the
appropriate function is called for execution. In case the
compiler is able to find a function prototype that matches in
respect of number of arguments, but not in respect of
argument types, the compiler uses the concept of integral
promotion of the actual arguments. For example, char to int or
float to double.
If the integral promotion also does not work, then the compiler
tries the implicit conversions to the actual arguments. It is also
called the implicit type casting. But using the implicit type
casting can also result in eventually the function call statement
matching with two function prototypes. For example, you call
add ( int ) function and pass integer argument to it. The
program consists of two add ( ) functions, one with formal
argument of long type and one with formal argument of double
type. First of all the compiler fails to find the exact match and
then it tries the integral promotion of actual arguments which
also fails. Then it tries the implicit type conversion of actual
argument. Implicit type conversion of actual argument will lead
to ambiguity error as the integer type can be implicitly
converted to both the long and double type.
Now you will see programs that will help you better understand
the concept of function overloading.

Program 1
To find the sum of two numbers
// header files

# include < iostream.h >

# include < conio.h >

//definition of class

class add

private:

int var1 ;
int var2 ;

public:

// default constructor function

add ( )

var1 = 0 ;

var2 = 0 ;

void set ( int a, int b )

var1 = a ;

var2 = b ;

void display ( )

cout<<" \n Value of data member var1 :- " << var1 ;

cout<<" \n Value of data member var2 :- " << var2 ;

cout<<" \n Sum of two data members is :- " << var1


+ var2 ;

};

void main( )

// object of class add

add obj1;
float a = 12.5 , b = 13.3 ;

//call to member function of obj1

obj1.set ( a , b ) ;

// call to member function of obj1

obj1.display ( ) ;

getch () ;

Will this program execute successfully? Must be wondering!


what's wrong with this program.
Inside the main ( ), one object of class add is declared using the
following statement:
// object of class add

add obj1;

It is followed by a statement used to call the member function


of class add:
//call to member function of obj1

obj1.set ( a , b ) ;

Which member function will be called? Must be wondering


again! What's so difficult in the question. Obviously the
following member function of class add will be called:
void set ( int a , int b )

var1 = a ;

var2 = b ;

}
Wait! The formal arguments used in the member
function are of integer data type and actual arguments
passed in the function call statement are of float type.
The answer to the question whether the program will
execute successfully or not is, yes.

Once the compiler fails to find a member function that exactly


matches the function call statement, compiler tries the implicit
conversions to the actual arguments. The actual arguments of
float type are implicitly type casted to integer type and
member function set ( ) is called for execution.

Output:
Value of data member var1 :- 12

Value of data member var2 :- 13

Sum of two data members is :- 25


Because the actual arguments are type casted to integer type,
the actual values passed to the formal arguments are 12 and
13 respectively.

Program 2
To implement overloading of sum function (keeping type
of arguments different)
// header files
# include < iostream.h >
# include < conio.h >
//definition of class
class add
{
private:
int var1 ;
int var2 ;
float var3 ;
float var4 ;
public:
// default constructor function
add ( )
{
var1 = 0 ;
var2 = 0 ;
}
// overloaded function with integer arguments
int sum ( int a , int b )
{
cout<< " \n Function to add two integer numbers " ;
var1 = a ;
var2 = b ;
return ( var1 + var2 ) ;
}
// overloaded function with float arguments
float sum ( float a , float b )
{
cout<< \n Function to add two float numbers " ;
var3 = a ;
var4 = b ;
return ( var3 + var4 ) ;
}
};
void main ( )
{
// object of class add
add obj1;
float fa = 12.5 , fb = 13.3 , ftotal ;
int ia = 18 , ib = 20 , itotal ;
// call to overloaded member function using float arguments
ftotal = obj1.sum ( fa , fb ) ;
cout<< " \n Sum of " << fa << " and " << fb << " is " <<
ftotal ;
// call to overloaded member function using integer arguments
itotal = obj1.sum ( ia , ib ) ;
cout<< " \n Sum of " << ia << " and " << ib << " is " <<
itotal ;
getch ( ) ;
}

In the last program function sum ( ) is overloaded.


int sum ( int a , int b )
float sum ( float a , float b )

Both the functions share the same name. The first instance
accepts two integer arguments and the second instance
accepts two float arguments. Following function call statement
will result in the execution of member function with formal
arguments of integer type:
itotal = obj1.sum ( ia , ib ) ;
Because the actual arguments are also of the integer type.
Similarly, the following function call statement will result in the
execution of member function with formal arguments of float
type:
ftotal = obj1.sum ( fa , fb ) ;
Because the actual arguments are also of float type.

Output:
Function to add two float numbers
Sum of 12.5 and 13.3 is 25.8
Function to add two integer numbers
Sum of 18 and 20 is 38

Program 3
To implement overloading of average function (keeping
number of arguments different)
// header files
# include < iostream.h >
# include < conio.h >
// definition of class
class average
{
private:
int var1 ;
int var2 ;
int var3 ;
public:
// default constructor function
average ( )
{
var1 = 0 ;
var2 = 0 ;
var3 = 0 ;
}
// overloaded function with 2 integer arguments
int compute ( int a , int b )
{
cout<< " \n Function to find average of two integer
numbers " ;
var1 = a ;
var2 = b ;
return ( ( var1 + var2 ) / 2 ) ;
}
// overloaded function with 3 integer arguments
int compute ( int a , int b , int c )
{
cout<< " \n Function to find average of three integer
numbers " ;
var1 = a ;
var2 = b ;
var3 = c ;
return ( ( var1 + var2 + var3 ) / 3 ) ;
}
};
void main ( )
{
// object of class average
average obj1 ;
int a = 10 , b = 20 , c = 30 , avg ;
// call to overloaded member function using 2 arguments
avg = obj1.compute ( a , b ) ;
cout<< " \n Average of " << a << " and " << b << " is " <<
avg ;
// call to overloaded member function using 3 arguments
avg = obj1.compute ( a , b , c ) ;
cout<< " \n Average of " << a << " , " << b << " and " << c
<< " is " << avg ;
getch ( ) ;
}

In the last program function compute ( ) is overloaded.


int compute ( int a , int b )
int compute ( int a , int b , int c )

Both the functions share the same name. The first definition
accepts two integer arguments and the second instance
accepts three integer arguments. Following function call
statement will result in the execution of member function with
formal arguments of 2 integers:
avg = obj1.compute ( a , b ) ;
and the following function call statement will result in the
execution of member function with formal arguments of 3
integers:
avg = obj1.compute ( a , b , c ) ;
Output:
Function to find average of two integer numbers
Average of 10 and 20 is 15
Function to find average of three integer numbers
Average of 10, 20 and 30 is 20

12.5 Constructor overloading


Constructor is a special member function that is automatically
called when the object of the same class is created. You can
also overload the constructor function, i.e. have multiple
constructor functions in the member list of the same class.

Program 4
To implement constructor overloading
// header files
# include < iostream.h >
# include < conio.h >
// definition of class
class add
{
private:
int var1 ;
int var2 ;
public:
// default constructor function
add ( )
{
cout<<" \n Default constructor called " ;
var1 = 0 ;
var2 = 0 ;
}
// parameterized constructor function
add ( int a , int b )
{
cout<<" \n Parameterized constructor called " ;
var1 = a ;
var2 = b ;
}
// copy constructor function
add ( add & obj )
{
cout<<" \n Copy constructor called " ;
var1 = obj.var1 ;
var2 = obj.var2 ;
}
void display ( )
{
cout<< " \n Value of var1 = " << var1 << " and var2
= " << var2 ;
}
};
void main ( )
{
// objects of class add
add obj1;
add obj2 ( 10 , 20 ) ;
add obj3 ( obj2 ) ;
cout<< " \n Value of data members with default constructor " ;
obj1.display ( ) ;
cout<< " \n Value of data members with parameterized
constructor " ;
obj2.display ( ) ;
cout<< " \n Value of data members with copy constructor " ;
obj3.display ( ) ;
getch ( ) ;
}
Output:

Default constructor called

Parameterized constructor called

Copy constructor called

Value of data members with default constructor

Value of var1 = 0 and var2 = 0

Value of data members with parameterized constructor

Value of var1 = 10 and var2 = 20

Value of data members with copy constructor

Value of var1 = 10 and var2 = 20

13.2 Operator overloading


Operator overloading is a key concept of C++ programming.
Operator overloading is a type of polymorphism and is used
to give new definition or create multiple forms of
operators already available in programming language. A
number of operators are available in C++ programming
language. Each operator in C++ has a pre-defined meaning.
The output for the same is also according to its pre-defined
meaning.
For example,
Plus operator '+' is used to find the sum of two numbers.
For instance,
a = 12 + 13
here the '+' operator will add '12' and '13' and the output is
'25' which will be assigned to 'a'. In the last statement
assignment operator '=' is also used with '+' operator.
Assignment operator is used to assignment the outcome of
expression on right side of assignment operator to the variable
on left side of assignment operator.

Now, you are clear with the concept of operator and its
operating rules and regulations. Operator overloading is the
concept of giving new meanings to already available operators
in C++. Overloading an operator does not change the basic
meaning of the operator. The overloaded operator still behaves
the same when it is applied to non class objects or types like
integer, float or char.
Only the operators that are pre-defined by C++ compiler can
be overloaded. Overloading is done to give new meaning to
these operators and operator overloading cannot be used to
create or define new operators. Overloading an operator is
restricted to giving additional meaning to the operator and you
cannot change the behavioral attributes of the operator. By
behavioral attributes we mean the precedence, associativity
and syntax for the operator.

Once an operator is overloaded, it can be applied on class


objects just as you apply the operators on built-in data types.
Consider the following statement for example,
Class_Object1 = Class_Object2 + Class_Object3
Class_object++;
void operator ++ ()
class_object_2 = Class_object++;
class_name operator ++ ()
class_object1 = class_object2 + class_object3;
class_name operator + (class_name)

Let us consider that plus '+' operator has been overloaded for
some class and Class_Object1, Class_Object2, and
Class_Object3 are 3 objects of the same class. '+' in the last
statement is treated as function called operator function.
Operator function is discussed in the next section. Interestingly
not all operators available in C++ can be overloaded.

Following is the list of some of the operators that


cannot be overloaded in C++ programming language:

Scope resolution operator ::


Dot operator .
Conditional operator ?:
Pointer-to-member operator .*
Preprocessor #
sizeof()

1. Conditional operator cannot be overloaded because it is


applied on 3 operands and C++ does not provide mechanism
to overload the same.

2. sizeof() operator is used for certain built-in operations. Like


incrementing a pointer variable to access each element of an
array implicitly. Hence it is not overloaded as it can lead to
confusion. For similar reasons the overloading of # operator is
also avoided in C++.

3. It also not feasible overload the scope resolution operator


(::). Consider for example,
student::input, both the student and input are identifiers known
to compiler and are not any expressions or variables that
represent some value. Also the :: operator is used to perform
scope resolution at compile time rather than evaluate the
expression.

4. It may be possible to overload the dot (.) operator. But it may


lead to some confusion. If the dot (.) is eventually overloaded,
the question may arise if the dot is used for object overloading
or to access an object referred to by dot (.) operator. For same
reasons overloading of the Pointer-to-member operator .* is
also avoided in C++.
13.2.1 Operator Function

Operator overloading can be achieved with the help of a special


function called the operator function. It means you have to
write a function in order to overload an operator and it shares
all the features of a normal function in C++. The operator
function will also have a function header, function body that
can contain a return statement just like any function in C++.
The body of the operator function determines the operation to
be performed by it and it can be different from the normal
behavior of that operator. Hence it is the body of the operator
function that determines the new meaning of the operator.
Beside all the similarities there are a few differences between
the function header of normal function and the operator
function.
Following is the syntax for function header of a normal function

Return_Type Function_name (Argument_List)


Whereas following is the function header of an operator
function.
Return_Type operator Operator_Symbol ( Argument list )

The difference between the two is in the function identifier or


function name. you are free to choose any valid identifier for
the normal function. But the identifier for the operator function
is the operator symbol pre-defined by the C++ compiler and is
followed the keyword operator to tell the compiler that it is an
operator function.

Consider the following function header for the operator


function to overload the binary plus '+' operator:
Class_Name operator + (Class_name Object_name)

Also the function call statement for the operator function is


different from the function call statement of the normal
member function. You place call to the member function using
the dot (.) operator and call to the operator unction is placed
using the operator symbol pre-defined by the compiler. For
example, you want to find the sum of two objects and assign it
to the third object, the same can be achieved using a call to the
member function as follows:
Object_Name1 =
Object_Name2.Function_Name(Object_Name3);

And the same can be achieved using a call to operator function


as follows:
Object_Name1 = Object_Name2 + Object_Name3;

13.3 Overloading Unary operator


Unary operators are used to apply operator on single operand.
Some of the examples of unary operators in C++ programming
are ++, --, +, -, !, ~. Operator function for overloading unary
operator does not have any argument in the argument list. In
this section you will learn the implementation of overloading
unary minus '-' operator and also overloading increment
operator. Increment operator comes in two variations known as
post increment and pre increment. Treatment of both variations
of increment operator are different in C++ and has also been
discussed latter in this lesson. Following is the program to
overload the unary minus operator.

Program 1
To overload the unary minus '-' operator
//header files
#include<iostream.h>
#include<conio.h>
//class definition
class MINUS
{
private:
int var1;
public:
//constructor
MINUS ()
{
var1 =0;
}
void input()
{
cout<<”\nEnter the value of member var1 :- “;
cin>>var1;
}
// definition of operator function for unary '-' operator
MINUS operator - ()
{
MINUS temp;
temp.var1 = -var1;
return temp;
}
void display()
{
cout<<"\nValue of member var1 :- "<<var1;
}
};

void main()
{
//objects of class MINUS
MINUS obj1;
//call to member function of obj1
obj1.input();
//call to operator function for overloading unary minus '-'
operator
obj1 = -obj1;
//call to member function of obj1
obj2.display();
getch();
}
Following is the operator function used in the last program to
overload the unary minus '-' operator:
MINUS operator - ()
{
MINUS temp;
temp.var1 = -var1;
return temp;
}
Return type is the class type itself. The statement used to call
the operator function:
Obj1 = -obj1;
Here the call to the operator function is done for the object obj1
and the temp object returned in the operator function is
assigned to obj1.

Output:

Enter the value of member var1 :- 45


Value of member var1 :- -45

As already stated earlier in this SLM, overloading the increment


or decrement operator comes in two variations. One is
overloading the pre increment operator and one is overloading
the post increment operator. C++ provides its users with the
mechanism to differentiate between the two. If the programmer
explicitly does not differentiate between the two, then the
same operator function is used for both the pre increment and
post increment operators.
Following is the program where only one operator function is
used for both types of increments.

Program 2
To implement increment operator '++' using single
operator function

//header files
#include <iostream.h>
#include<conio.h>
//definition of class
class INC
{
private:
int var1;
public:
//constructor function
INC( )
{
var1= 0;
}
void input ( )
{
cout<<”\nEnter value for data member var1 :- “;
cin>>var1;
}
// definition of operator function to overload increment
operator '++'
void operator ++ ( )
{
var1++;
}
void display( )
{
cout<<”\nValue of data member var1 :- “<<var1;
}
};

void main( )
{
// object of class INC
INC obj1;
//call to member function of obj1
obj1.input( );
// call to operator function '++'
obj1++;
// call to operator function '++'
++obj1;

// call to member function of obj1


obj1.display();
getch();
}
The only operator function used in the last program is:
void operator ++ ( )
{
var1++;
}

And the program consists of two operator function call


statements:
// call to operator function '++'
obj1++;
// call to operator function '++'
++obj1;

The first statement uses the post increment scheme and the
second statement uses the pre increment scheme. Because the
program is written using a single operator function and the
program also does not explicitly differentiate between pre and
post increment, same operator function is executed for both
the operator function call statements.

Output:
Enter value for data member var1 :- 47
Value of data member var1 :- 49

It is possible to create two separate operator functions for post


increment and pre increment schemes. The compiler is able to
differentiate between the two at compile time and able to bind
the function call statements to their respective operator
functions.
Program 3
To overload both the post and pre increment operators

//header files
#include <iostream.h>
#include<conio.h>
//class defintion
class INC
{
private:
int var1;
public:
//constructor function
unaryinc ( )
{
var1 = 0;
}
void input ( )
{
cout<<”\nEnter value of data member var1 :- “;
cin>>var1;
}
// definition of operator function for pre increment
scheme
INC operator ++ ( )
{
INC temp;
var1++;
temp.var1 = var1;
return temp;
}
// definition of operator function for post increment
scheme
INC operator ++ ( int )
{
INC temp;
temp.var1 = var1;
var1++;
return temp;
}
void display( )
{
cout<<”\nValue of member function var1 :- “<<var1;
}
};

void main( )
{
// objects of class INC
INC obj1, obj2;

cout<<”\nObject 1”;
//call to memebr function of obj1
obj1.input( );
// call to pre increment operator function
obj2 = ++obj1;
cout<<”\nValue of data member var1 of object1 after pre
increment”;
obj1.display();
cout<<”\nValue of data member var1 of object2 after pre
increment”;
obj2.display();
// call to post increment operator function
obj2 = obj1++;
cout<<”\nValue of data member var1 of object1 after post
increment”;
obj1.display();
cout<<”\nValue of data member var1 of object2 after post
increment”;
obj2.display();
getch();
}

Two separate operator functions are used in the last program:


FOR OVERLOADING PRE INCREMENT OPERATOR
INC operator ++ ( )
{
INC temp;
var1++;
temp.var1 = var1;
return temp;
}
The function header is same as that of the function header of
operator function used in the program previous to this. The
value of data member var1 is increment first and then assigned
to the data member var1 of temp object before it is returned.

FOR OVERLOADING POST INCREMENT OPERATOR


INC operator ++ (int )
{
INC temp;
temp.var1 = var1;
var1++;
return temp;
}
The function header is slightly different from the function
header of operator function used for overloading pre increment
operator. As you can see in the function header of operator
function for the post increment operator, 'int' is passed as
argument. The value of data member var1 assigned to the
data member var1 of temp object and is increment after that.
Hence the temp object returns the non-incremented value.

Output:
Object 1
Enter value of data member var1 :- 10

Value of data member var1 of object1 after pre increment


Value of member function var1 :- 11
Value of data member var1 of object2 after pre increment
Value of member function var1 :- 11

Value of data member var1 of object1 after post increment


Value of member function var1 :- 12
Value of data member var1 of object2 after post increment
Value of member function var1 :- 11

13.4 Overloading binary operator

Overloading binary operator is slightly difficult then overloading


a unary operator. Binary operator is used to perform operation
on two operands. All arithmetic operators are examples of
binary operators. In case of overloading unary operator, no
arguments were passed to the operator function. But in case of
overloading binary operator, one object is passed as argument
to the operator function. Consider the following statement
which an operator function call statement:
Object_Name1 = Object_Name2 + Object_Name3;
The Object_Name2 object places call its operator function '+'
and Object_Name3 is passed as argument to the function. The
addition of two objects is then returned to Object_Name2.
Following is the program to overload the binary plus '+'
operator.

Program 4
To overload binary operator plus '+'
//header files
#include <iostream.h>
#include<conio.h>
//class definition
class ADD
{
private:
int var1;
int var2;
public:
//constructor function
ADD( )
{
var1 = 0;
var2 = 0;
}
void input ( )
{
cout<<”\nEnter value of data member var1 :- “;
cin>>var1;

cout<<”\nEnter value of data member var2 :- “;


cin>>var2;
}
//definition of operator function to overload binary plus '+'
operator
ADD operator + ( ADD obj3 )
{
ADD temp;
temp.var1 = var1 + obj3.var1;
temp.var2 = var2 + obj3.var2;
return temp;
}
void display( )
{
cout<<”\nValue of data member var1 :- “<<var1;
cout<<”\nValue of data member var2 :- “<<var2;
}
};

void main( )
{
ADD obj1, obj2, obj3;
cout<<”\nObject 2”;
//call to member function of object 2
obj2.input( );
cout<<”\nObject 3”;
//call to member function of object 3
obj3.input( );
// call to the operator function '+'
obj1 = obj2 + obj3;
cout<<”\nObject 1 after addition”;
obj1.display();
getch();
}

Last program is used to overload the binary operator '+' using


the following operator function:
ADD operator + ( ADD obj3 )
{
ADD temp;
temp.var1 = var1 + obj3.var1;
temp.var2 = var2 + obj2.var2;
return temp;
}
The function call statement used to call the operator function:
obj1 = obj2 + obj3;

obj3 is passed as actual argument. obj2 is the object that


places call to the operator function.
temp.var1 = var1 + obj3.var1;
In the last statement, var1 belongs to the object that has called
the operator function which in this case is obj2.

Output:
Object 2
Enter value of data member var1 :- 10
Enter value of data member var2 :- 12

Object 3
Enter value of data member var1 :- 11
Enter value of data member var2 :- 14

Object 1 after addition


Value of data member var1 :- 21
Value of data member var2 :- 26

You might also like