Polymorphism
Polymorphism
Introduction
Polymorphism is the combination of two greek words one is poly means many and other
one is morphism means form.
“whose meaning is same having different behavior.”
Types –
a) Compile Time polymorphism: achieved by compile time called static
polymorphism/ early binding.
Example: Method overloading.
Polymorphism
Pointer is a variable which can hold the address of a memory location rather than the
value at the location. Consider the following statement
int num = 84;
This statement instructs the compiler to reserve a 2-byte of memory location and puts
the value 84 in that location. Assume that the compiler allocates memory location 1001
to num. Diagrammatically, the allocation can be shown as:
num Variable name
84 Value
Abstract class:
A class which contain atleast one pure virtual function. We cannot declare the object
of abstract class.
Syntax:
Class A
{
Public:
Virtual void show()=0;
};
Virtual Functions
Virtual functions, one of advanced features of OOP is one that does not really exist but
it appears real in some parts of a program. This section deals with the polymorphic
features which are incorporated using the virtual functions.
Remember that the keyword virtual should not be repeated in the definition if the
definition occurs outside the class declaration. The use of a function specifier virtual in
the function definition is invalid.
For example
class point {
intx ;
inty ;
public:
virtual void display ( );
};
virtual void point: : display ( ) //error
{
Function Body
}
A virtual function cannot be a static member since a virtual member is always a member
of a particular object in a class rather than a member of the class as a whole.
class point {
int x ;
int y ;
public:
virtual static int length ( ); //error
};
int point: : length ( )
{
Function body
}
A virtual function cannot have a constructor member function but it can have the
destructor member
function.
class point {
int x ;
int y ;
public:
virtual point (int xx, int yy) ; // constructors, error
void display ( ) ;
int length ( ) ;
};
A destructor member function does not take any argument and no return type can be
specified for it
not even void.
class point {
int x ;
int y ;
public:
virtual point (int xx, int yy) ; //invalid
void display ( ) ;
int length ( ) ;
Late Binding
As we studied in the earlier unit, late binding means selecting functions during the
execution. Though late binding requires some overhead it provides increased power and
flexibility. The late binding is implemented through virtual functions as a result we have
to declare an object of a class either as a pointer to a class or a reference to a class.
For example the following shows how a late binding or run time binding can be carried
out with the help of a virtual function. The following program demonstrates the run
time binding of the member functions of a class. The same message is given to access
the derived class member functions from the array of pointers. As function are declared
as virtual, the C++ compiler invokes the dynamic binding.
#include <iostream>
using namespace std;
class baseA
{
public :
virtual void display() {
cout<< "One \n"; }
};
class derivedB : public baseA
{
public:
virtual void display() {
cout<< "Two\n"; }
};
class derivedC: public derivedB
{
public:
virtual void display ( ) {
cout<< "Three \n"; }
};
int main ( )
{
baseA obja; //define three objects
derivedB objb;
derivedC objc;
baseA *ptr [3]; //define an array of pointers to baseA
ptr [0] = &obja;
ptr [1] = &objb;
ptr [2] = &objc;
for ( int i = 0; i <=2; i ++ )
ptr [i]->display (); //same message for all objects
}
Output
One
Two
Three
The program listed below illustrates the static binding of the member functions of
a class. In program there are two classes student and academic. The class academic is
derived from class student. The two member function getdata and display are defined
for both the classes. *obj is defined for class student, the address of which is stored in
the object of the class academic. The functions getdata ( ) and display ( ) of student class
are invoked by the pointer to the class.
#include<iostream>
using namespace std;
class student
{
private:
int rollno;
char name [20];
public:
void getdata();
void display();
};
class academic: public student
{
private:
char stream;
public:
void getdata();
void display();
};
void student :: getdata()
{
cout<< "Enter Roll no\n";
cin>> rollno;
cout<< "Enter Name \n";
cin>> name;
}
void student:: display()
{
cout<< "the student’s roll number is : "<< rollno;
cout<< "\n and name is : " << name ;
cout<< endl;
}
void academic :: getdata()
{
cout<< "Enter stream of a student? \n";
cin >> stream;
}
void academic :: display()
{
cout<< "Students stream \n";
cout << stream << endl;
}
int main()
{
student *ptr;
academic obj;
ptr = &obj;
ptr -> getdata();
ptr -> display();
}
output
Enter Roll no : 20
Enter Name : rajat
the student’s roll number is : 20
and name is : rajat
The program listed below illustrates the dynamic binding of member functions of a
class. In this program there are two classes student and academic. The class academic
is derived from student. Student function has two virtual functions getdata ( ) and
display (). The pointer for student class is defined and object . for academic class is
created. The pointer is assigned the address of the object and function of derived class
are invoked by pointer to student.
#include <iostream>
using namespace std;
class student
{
private:
int rollno;
char name [20];
public:
virtual void getdata();
virtual void display();
};
class academic: public student
{
private:
char stream[10];
public:
void getdata ();
void display () ;
};
void student:: getdata()
{
cout<< "Enter Rollno\n";
cin >> rollno;
cout<< "Enter Name \n";
cin >>name;
}
void student:: display()
{ cout<< "The student’s roll number is "<< rollno;
cout<< "and name is "<<name; }
void academic:: getdata()
{ cout << "Enter stream of a student? \n";
cin>> stream; }
void academic:: display()
{
cout<< "Students stream : ";
cout<< stream << endl;
}
int main()
{
student *ptr;
academic obj;
ptr = &obj;
ptr->getdata();
ptr->display();
}
output
Enter stream of a student?
CSE
Students stream : CSE
Pure Virtual Functions
1) Pure virtual function are virtual function which have no definition. They start with
virtual keyword and ends with equal to zero.
2) If we don’t override the virtual function in derive class than derive class also becomes
abstract class.
3) We cannot change the signature of pure virtual function.
The following program demonstrates how a pure virtual function is defined, declared
and invoked from the object of a derived class through the pointer of the base class.
#include<iostream>
using namespace std;
class A
{
public:
virtual void show()=0;
void disp()
{
cout<<"Hi i am base class"<<"\n";
}
};
class B: public A
{
public:
void show()
{
cout<<"Hi i am derived class"<<"\n";
}
};
int main()
{
B obj;
obj.disp();
obj.show();
}
Output:
Hi i am base class
Hi i am derived class
#include<iostream>
using namespace std;
class A
{
public:
virtual void show()=0;
void disp()
{
cout<<"Hi i am base class"<<"\n";
}
};
class B: public A
{
public:
void show()
{
cout<<"Hi i am derived class"<<"\n";
}
};
int main()
{
A *p;
B obj;
p=&obj;
p->disp();
p->show();
}
Output:
Hi i am base class
Hi i am derived class
In the example there are two classes employee and grade. The class employee is base
class and the grade is derived class. The functions getdata ( ) and display ( ) are declared
for both the classes. For the class employee the functions are defined with empty body
or no code inside the function. The code is written for the grade class. The methods of
the derived class are invoked by the pointer to the base class.
#include<iostream>
using namespace std;
class employee
{
int code;
char name [20] ;
public:
virtual void getdata ( ) ;
virtual void display ( ) ;
};
class grade: public employee
{
char grd [90] ;
float salary ;
public :
void getdata ( ) ;
void display ( );
};
void employee :: getdata()
{
}
void employee:: display()
{
}
void grade :: getdata()
{
cout<< " enter employee’s grade ";
cin>> grd ;
cout<< "\n enter the salary " ;
cin>> salary;
}
void grade :: display()
{
cout<<" Grade salary \n";
cout<< grd<< " "<< salary<< endl;
}
int main()
{
employee *ptr;
grade obj;
ptr = &obj;
ptr->getdata();
ptr->display();
}
Output
enter employee’s grade A
enter the salary 250000
Grade salary
A 250000
Object Slicing:
In C++, a derived class object can be assigned to a base class object, but the other
way is not possible.
Object Slicing happens when a derived class object is assigned to a base class object,
additional attributes of a derived class object are sliced off to form the base class
object.
#include <iostream>
using namespace std;
class Base
{
protected:
int i;
public:
Base(int a) { i = a; }
virtual void display()
{ cout << "I am Base class object, i = " << i << endl; }
};
int main()
{
Base b(33);
Derived d(45, 54);
somefunc(b);
somefunc(d); // Object Slicing, the member j of d is sliced off
return 0;
}
Output:
We can avoid above unexpected behavior with the use of pointers or references. Object
slicing doesn’t occur when pointers or references to objects are passed as function
arguments since a pointer or reference of any type takes same amount of memory. For
example, if we change the global method myfunc() in the above program to following,
object slicing doesn’t happen.
Output:
We get the same output if we use pointers and change the program to following.
Output:
Object slicing can be prevented by making the base class function pure virtual there
by disallowing object creation. It is not possible to create the object of a class which
contains a pure virtual method.
LECTURE-33