POLYMORPHISM
Prof. VARANG N. ACHARYA Asst. Prof. & Head
MCA Department
Parul Institute of Engineering & Technology
Vadodara
Phone : (02668) 260300, 260344
URL : http://sites.google.com/site/vnaclass/
Email : [email protected]
• Polymorphism is the property of the same object to behave
differently in different context given the same message
Prof. VARANG N. ACHARYA Asst. Prof. & Head
MCA Department
Parul Institute of Engineering & Technology
Vadodara
Phone : (02668) 260300, 260344
URL : http://sites.google.com/site/vnaclass/
Email : [email protected]
POLYMORPHISM
Prof. VARANG N. ACHARYA Asst. Prof. & Head
MCA Department
Parul Institute of Engineering & Technology
Vadodara
Phone : (02668) 260300, 260344
URL : http://sites.google.com/site/vnaclass/
Email : [email protected]
Compile Time and Runtime Polymorphism
• Compile time - Function Overloading, Operator Overloading
• Run time - Virtual function with inheritance
Prof. VARANG N. ACHARYA Asst. Prof. & Head
MCA Department
Parul Institute of Engineering & Technology
Vadodara
Phone : (02668) 260300, 260344
URL : http://sites.google.com/site/vnaclass/
Email : [email protected]
Pointer to Object
• Normal objects cannot help in achieving runtime
polymorphism
• It is possible to achieve it only by setting or defining pointer to
objects
Prof. VARANG N. ACHARYA Asst. Prof. & Head
MCA Department
Parul Institute of Engineering & Technology
Vadodara
Phone : (02668) 260300, 260344
URL : http://sites.google.com/site/vnaclass/
Email : [email protected]
Pointer to Object…
Class demo
{
…..
}
demo DemoObj;
demo *ptrDemoObj;
ptrDemoObj = & DemoObj;
• Look at the code above. Pointer to object is similar to other pointers with no difference
Prof. VARANG N. ACHARYA Asst. Prof. & Head
MCA Department
Parul Institute of Engineering & Technology
Vadodara
Phone : (02668) 260300, 260344
URL : http://sites.google.com/site/vnaclass/
Email : [email protected]
this Pointer
The this pointer is a pointer to an object invoked by the member function. Following code explains the usage of this pointer.
#include<iostream.h>
#include<string.h>
using namespace std;
class person
{
string name;
int age;
public:
person(string tempname, int tempage)
{
name = tempname;
age = tempage;
}
person elder (person otherperson)
{
if(age>otherperson.age)
return *this;
//returning the invoking object
else
return otherperson;
}
friend ostream & operator << (ostream & tempout, person &
tempperson);
};
ostream & operator << (ostream & tempout, person &
tempperson)
{
tempout << "The person "<<tempperson.name<<" is " <<
tempperson.age << " years old\n";
return tempout;
}
void main()
{
person Steve(“Steve Waugh", 35);
person Mark(“Mark Waugh", 20);
person bigbrother = Steve.elder(B);
cout<<bigbrother;
}
Output of the Programme
The person Steve Waugh is 35 years old
• This example shows how *this returns the elder brothers
object. Steve is an elder brother. So when we call
Steve.elder(Mark) the function elder is called where the
age of invoking the object is compared with the age of
Mark’s object. Steve’s age is more. So *this is returned
from the function.
Prof. VARANG N. ACHARYA Asst. Prof. & Head
MCA Department
Parul Institute of Engineering & Technology
Vadodara
Phone : (02668) 260300, 260344
URL : http://sites.google.com/site/vnaclass/
Email : [email protected]
Compatibility of Derived and Base Class Pointers
• Base class pointers can point to a derived class object
• No casting is required
• Look at the following code
BaseClass BC;
DerivedClass DC : public BaseClass;
BaseClass *ptrBC;
DerivedClass ptrDC;
ptrBC = &BC; //pointer and content are of similar types
ptrDC = &DC; //pointer and content are of similar types
ptrBC = &DC; // this is done without any casting
ptrDC = &BC; // not allowed
Prof. VARANG N. ACHARYA Asst. Prof. & Head
MCA Department
Parul Institute of Engineering & Technology
Vadodara
Phone : (02668) 260300, 260344
URL : http://sites.google.com/site/vnaclass/
Email : [email protected]
Compatibility of Derived and Base Class Pointers…
Though the derived class and base class pointers seem compatible, there are some
points to note.
1. Base class pointer can be made to point to a derived class object, but is cannot
access the original members of the derived class. It can only access base class
members of the derived class object. The base class pointer can see only base
class subobject embedded in the derived class object, not the additional part of
the derived class. However, if any of the functions defined in derived class is
defined as virtual in base class, the case will be different.
2. In no case, derived class object pointer is made to point to the base class. It can
only be done by casting. i.e. ptrDC = &BC will give error, but ptrDC = (DC *) &BC
will work.
3. The increment and decrement operator with base pointer types do not behave as
expected. A base class pointer is always incremented as per the base class size
and a derived class pointer is always incremented as per the derived class size.
Hence, if a base class pointer is pointing to a derived class object, after increment,
it might not point to the next derived object.
Prof. VARANG N. ACHARYA Asst. Prof. & Head
MCA Department
Parul Institute of Engineering & Technology
Vadodara
Phone : (02668) 260300, 260344
URL : http://sites.google.com/site/vnaclass/
Email : [email protected]
Subobject Concept
• Whenever a base class is inherited, the derived class contains the base class subobject
• In case of multiple inheritance, the derived class contains multiple subobjects.
• In case of multilevel inheritance, we have n subobjects in the class derived at n+1 level
• Compiler automatically manages the pointer to point to the respective subobject of the derived class in case of multiple or multilevel inheritance
• e.g.
BaseClass1 BC1;
BaseClass2 BC2;
DerivedClass dc : public BaseClass1, BaseClass2;
BaseClass1 *ptrBC1;
BaseClass2 *ptrBC2;
DerivedClass ptrDC;
ptrBC1 = &DC; // point to subobject of BaseClass1
ptrBC2 = &DC; // point to subobject of BaseClass2
Prof. VARANG N. ACHARYA Asst. Prof. & Head
MCA Department
Parul Institute of Engineering & Technology
Vadodara
Phone : (02668) 260300, 260344
URL : http://sites.google.com/site/vnaclass/
Email : [email protected]
Base Class and Derived Class Member Functions
• It is possible to have two different member functions with the same name, one in
base class and other in derived class
• The function in the derived class is known as overloaded function in this case
• It is analogues to having a global and a local variable with the same name
• So, if we refer to a function in derived class, the derived class function is executed
• It is interesting to check the case where the pointer to the base class is made to
point to derived class, and the overloaded function is called using that pointer.
Prof. VARANG N. ACHARYA Asst. Prof. & Head
MCA Department
Parul Institute of Engineering & Technology
Vadodara
Phone : (02668) 260300, 260344
URL : http://sites.google.com/site/vnaclass/
Email : [email protected]
Base Class and Derived Class Member Functions…
#include<iostream.h>
#include<string.h>
using namespace std;
class shape
{ int linestyle;
int fillcoller;
public:
void draw()
{
cout<<"Shape is drawn \n";
}
};
class circle:public shape
{ int radius;
int centerpointX,centerpointY;
public:
void draw()
{
cout<<"Circle is drawn \n";
}
};
void main()
{
shape someshape, *ptrshape;
circle ring;
someshape.draw();
ring.draw();
ptrshape = ˚
ptrshape->draw(); // When we use a base class pointer pointing to
the derived class, the function called is from the
base class, not from the derived class
}
Output of program
Shape is drawn
Circle is drawn
Shape is drawn
Prof. VARANG N. ACHARYA Asst. Prof. & Head
MCA Department
Parul Institute of Engineering & Technology
Vadodara
Phone : (02668) 260300, 260344
URL : http://sites.google.com/site/vnaclass/
Email : [email protected]
Base Class and Derived Class Member Functions…
#include<iostream.h>
#include<string.h>
using namespace std;
class shape
{ int linestyle;
int fillcoller;
public:
virtual void draw()
{
cout<<"Shape is drawn \n";
}
};
class circle:public shape
{ int radius;
int centerpointX;
int centerpointY;
public:
void draw()
{
cout<<"Circle is drawn \n";
}
};
class rectangle:public shape
{
int lefttopx;
int lefttopy;
int rightbottomx;
int rightbottomy;
public:
someotherfunctin() //no draw defined here
{ // nothing
}
};
void main()
{
shape someshape, *ptrshape;
circle ring;
someshape.draw();
ring.draw();
ptrshape = ˚
ptrshape->draw();
rectangle square;
ptrshape = □
ptrshape->draw(); // this would still call draw() of shape chass
}
Output of the Program
Shape is drawn
Circle is drawn
Circle is drawn
Shape is drawn
Notice the Change. Now ptrshape->draw() calls draw() of circle,
not shape. In base class the function is defined as virtual. The
addition of word virtual makes the whole difference. When the
statement ptrshape->draw() is exucuted, it looks at the content
of the ptrshape at runtime, and then executes the draw()
function which is appropriate. This is the difference when we
use virtual function instead of normal function
Prof. VARANG N. ACHARYA Asst. Prof. & Head
MCA Department
Parul Institute of Engineering & Technology
Vadodara
Phone : (02668) 260300, 260344
URL : http://sites.google.com/site/vnaclass/
Email : [email protected]
Virtual Functions
• Virtual functions are special
• They are treated differently by the compiler
• The class has an additional storage requirement when at least one virtual function
is defined inside it
• A table is created additionally to store pointers to all virtual functions available to
all the objects of the class.
• The table is called virtual table
• A single pointer to the virtual table is inserted in all class objects when the class
contains at least one virtual function
• This pointer is known as vptr
• Whenever an object of such class wants to execute a virtual function, the table is
referred to and the appropriate function is called
Prof. VARANG N. ACHARYA Asst. Prof. & Head
MCA Department
Parul Institute of Engineering & Technology
Vadodara
Phone : (02668) 260300, 260344
URL : http://sites.google.com/site/vnaclass/
Email : [email protected]
Virtual Functions…
Few syntactical constraints on use of virtual functions:
1. The function name must be preceded by virtual keyword in the base class
2. The function in the derived class must have the same name as of the virtual
function defined in the base class and the same prototype. If the prototype is
different, the function is as good as overloaded function and not treated as virtual
function
3. The function in the derived class need not be preceded by the virtual keyword. If it
is preceded by virtual keyword, it makes no difference
4. If a function with the same name is not defined in the derived class, the original
base class function is invoked.
5. The virtual function must be defined in the base class; it may have an empty body
though
Prof. VARANG N. ACHARYA Asst. Prof. & Head
MCA Department
Parul Institute of Engineering & Technology
Vadodara
Phone : (02668) 260300, 260344
URL : http://sites.google.com/site/vnaclass/
Email : [email protected]
Virtual Functions…
6. For any real problem solving case using virtual function, the class hierarchy should
be present. The virtual functions are the members of the classes of the hierarchy.
They are called using either pointer to the base class or a reference to base class.
This implies that the functions must be members of base as well as derived class,
respectively
7. Polymorphism is achieved only using pointers to the base class. It is not possible
using objects. This known as static invocation of virtual function
8. Virtual constructors are not possible. Constructing a derived class object needs
specific construction of the base class subobject within. Obviously, their
constructors cannot be virtual. When an object is deleted, we may have virtual
destructor for destroying them, so the delete <pointer> operation works for the
object pointed to, irrespective of the pointer type. Here, it is allowed to provide
deletion of the entire derived class object while pointed to by a base class pointer.
(otherwise it would only delete base class subobject of the derived class). Anyway,
it is a good idea to have virtual destructors to avoid memory leaks
Prof. VARANG N. ACHARYA Asst. Prof. & Head
MCA Department
Parul Institute of Engineering & Technology
Vadodara
Phone : (02668) 260300, 260344
URL : http://sites.google.com/site/vnaclass/
Email : [email protected]
Default Arguments to Virtual Functions #include<iostream.h>
#include<string.h>
using namespace std;
class shape
{
int linestyle;
int fillcoller;
public:
virtual int draw(int size=100)
{
cout<<"Shape is drawn \n";
return size;
}
};
class circle:public shape
{
int radius;
int centerpointX;
int centerpointY;
public:
int draw(int size=200)
{
cout<<"Circle is drawn \n";
return size;
}
};
void main()
{
shape someshape, *ptrshape;
circle ring;
someshape.draw();
ring.draw();
ptrshape = ˚ // base class pointer pointing to derived class
// object
int drawsize = ptrshape->draw(); // now this draws a circle
cout<<"Draw size for circle using a base class pointer is :
"<<drawsize<<endl; // displays 100 instead of 200
circle *ptrcircle = ˚ //now we are using a derived class
//pointer to point to a derived class
// object
drawsize=ptrcircle->draw();
cout<<"Draw size for circle using a base class pointer is :
"<<drawsize<<endl; // display 200 correctly
}
Output of the program
Shape is drawn
Circle is drawn
Draw size for circle using a base class pointer is 100
Circle is drawn
Draw size for circle using a derived class pointer is 200
Prof. VARANG N. ACHARYA Asst. Prof. & Head
MCA Department
Parul Institute of Engineering & Technology
Vadodara
Phone : (02668) 260300, 260344
URL : http://sites.google.com/site/vnaclass/
Email : [email protected]
Default Arguments to Virtual Functions…
• When we use a base class pointer to point to a derived class
object, the default value of the base class function will be taken.
Here the function which is executed is correct, but with the default
value of the base class. On the other hand when we use a derived
class pointer, the default value of derived class function is taken.
• Therefore, we cannot use default parameters like a normal
function here.
• The solution here is to provide a local variable initialized in both
such classes and then to use default argument.
• If we need default arguments, they can be assigned values of
such local variables as in the next example.
• We only need to see if the user has supplied a value, if not, the
user has supplied a value by keeping a dummy default argument.
• If the argument equals to the dummy argument, the use has not
supplied a value and we can take the value from the local
variable.
Prof. VARANG N. ACHARYA Asst. Prof. & Head
MCA Department
Parul Institute of Engineering & Technology
Vadodara
Phone : (02668) 260300, 260344
URL : http://sites.google.com/site/vnaclass/
Email : [email protected]
Default Arguments to Virtual Functions… #include<iostream.h>
#include<string.h>
class shape
{
int linestyle;
int fillcoller;
public:
virtual int draw(int size=1)
{
cout<<"Shape is drawn \n";
int shapesize = 100;
if(size==1) // default case
size = shapesize;
return size;
}
};
class circle:public shape
{ int radius;
int centerpointX;
int centerpointY;
public:
int draw(int size=1)
{
cout<<"Circle is drawn \n";
int circlesize = 200;
if(size==1) // default case
size = circlesize;
return size;
}
};
void main()
{
shape someshape, *ptrshape;
circle ring;
someshape.draw();
ring.draw();
ptrshape = ˚ // base class pointer pointing to derived class
//object
int drawsize = ptrshape->draw(); // now this drows a circle
cout<<"Draw size for circle using a base class pointer is : “
<<drawsize<<endl;
circle *ptrcircle = ˚ // now we are using a derived class
//pointer to point to a derived class object
drawsize=ptrcircle->draw();
cout<<"Draw size for circle using a derived class pointer is : “
<<drawsize<<endl;
}
Output of the Program
Shape is drawn
Circle is drawn
Circle is drawn
Draw size for circle using a base class pointer is : 200
Circle is drawn
Draw size for circle using a derived class pointer is : 200
Prof. VARANG N. ACHARYA Asst. Prof. & Head
MCA Department
Parul Institute of Engineering & Technology
Vadodara
Phone : (02668) 260300, 260344
URL : http://sites.google.com/site/vnaclass/
Email : [email protected]
Using Virtual Functions… #include<iostream.h>
#include<ctime.h>
class figure; // forward declaration
class point
{
int x,y;
public:
point(int tempx=0, int tempy=0)
{
x = tempx; y = tempy;
}
int getx() const
{
return x;
}
int gety() const
{
return y;
}
friend ostream & operator << (ostream & tempout, point
& temppoint);
};
ostream & operator << (ostream & tempout, point & temppoint)
{
tempout<< "( "<<temppoint.getx() << ", "<<
temppoint.gety() << " )";
return tempout;
}
class shape
{
point position;
int color;
public:
virtual void draw()
{
cout<<" Shape is drawn ";
}
friend figure; // frgure is going to use parameters for
drawing shapes
};
class square:public shape
{
point leftbottom;
int length;
public:
square(point templeftbuttom, int templength)
{
leftbottom = templeftbuttom;
length = templength;
}
void draw()
{
cout<<"Square is drawn at " << leftbottom << "
and with length as " << length <<endl;
}
};
Prof. VARANG N. ACHARYA Asst. Prof. & Head
MCA Department
Parul Institute of Engineering & Technology
Vadodara
Phone : (02668) 260300, 260344
URL : http://sites.google.com/site/vnaclass/
Email : [email protected]
Using Virtual Functions… class triangle:public shape
{ point Avertex, Bvertex, Cvertex;
public:
triangle(point tempavertex, point tempbvertex, point
tempcvertex)
{
Avertex=tempavertex;
Bvertex=tempbvertex;
Cvertex=tempcvertex;
}
void draw()
{
cout<< "Triangle is drawn at " << Avertex <<" "
<<Bvertex << " " << Cvertex << endl;
}
};
class circle:public shape
{ point center;
int radius;
public:
circle(point tempcenter, int tempradius)
{
center = tempcenter;
radius = tempradius;
}
void draw()
{
cout<< "Circle is drawn at " << center <<" and
the radius is " << radius << endl;
} };
class figure
{
shape * images[25];
public:
figure()
{
srand( (unsigned)time( NULL ) );
for(int i=0; i<25; i++)
{ int randomvalues[6];
for(int j=0; j<6; j++)
{
randomvalues[i] = rand() % 50;
}
point position1(randomvalues[0], randomvalues[1]);
point position2(randomvalues[2], randomvalues[3]);
point position3(randomvalues[4], randomvalues[5]);
switch(int choice = rand() % 3)
{
case 0:
{
int length = rand() % 20;
images[i] = new square(position1, length);
break;
}
Prof. VARANG N. ACHARYA Asst. Prof. & Head
MCA Department
Parul Institute of Engineering & Technology
Vadodara
Phone : (02668) 260300, 260344
URL : http://sites.google.com/site/vnaclass/
Email : [email protected]
Using Virtual Functions… case 1:
{
images[i] = new triangle(position1, position2, position3);
break;
}
case 2:
{
int radius = rand() % 10;
images[i] = new circle(position1, radius);
break;
}
default:
cout<< choice << " is a wrong choice ";
}
}
}
void draw()
{
for (int i=0;i<25;++i)
images[i]->draw();
}
};
void main()
{
figure myFigure;
myFigure.draw();
}
Output of the Program
Square is drawn at ( 27, 1244768 ) and with length as 11
Triangle is drawn at ( 27, 0 ) ( 0, 30 ) ( 1244896, 0 )
Triangle is drawn at ( 27, 0 ) ( 48, 30 ) ( 1244896, 0 )
Square is drawn at ( 27, 0 ) and with length as 2
Circle is drawn at ( 27, 0 ) and the radius is 0
Triangle is drawn at ( 27, 0 ) ( 48, 13 ) ( 2, 1 )
Triangle is drawn at ( 27, 0 ) ( 48, 13 ) ( 2, 1 )
Triangle is drawn at ( 27, 0 ) ( 48, 13 ) ( 2, 1 )
Square is drawn at ( 27, 0 ) and with length as 13
Square is drawn at ( 27, 0 ) and with length as 17
Circle is drawn at ( 27, 0 ) and the radius is 4
Triangle is drawn at ( 27, 0 ) ( 48, 13 ) ( 2, 1 )
Triangle is drawn at ( 27, 0 ) ( 48, 13 ) ( 2, 1 )
Square is drawn at ( 27, 0 ) and with length as 19
Triangle is drawn at ( 27, 0 ) ( 48, 13 ) ( 2, 1 )
Circle is drawn at ( 27, 0 ) and the radius is 5
Circle is drawn at ( 27, 0 ) and the radius is 2
Triangle is drawn at ( 27, 0 ) ( 48, 13 ) ( 2, 1 )
Circle is drawn at ( 27, 0 ) and the radius is 8
Triangle is drawn at ( 27, 0 ) ( 48, 13 ) ( 2, 1 )
Square is drawn at ( 27, 0 ) and with length as 15
Square is drawn at ( 27, 0 ) and with length as 5
Square is drawn at ( 27, 0 ) and with length as 4
Triangle is drawn at ( 27, 0 ) ( 48, 13 ) ( 2, 1 )
Circle is drawn at ( 27, 0 ) and the radius is 6
Prof. VARANG N. ACHARYA Asst. Prof. & Head
MCA Department
Parul Institute of Engineering & Technology
Vadodara
Phone : (02668) 260300, 260344
URL : http://sites.google.com/site/vnaclass/
Email : [email protected]
Pure Virtual Function
• When a class does not have any object, there is no need to have
functions for it as there is no object to utilize those functions
• Consider a case of class Shape that we have discussed earlier
• We will never have an object of class Shape in actual working
environment
• If we define draw() in the class, we will never be able to execute it
• It is important to understand that, because draw is a virtual function, we
cannot have polymorphism without draw() defined in class Shape
• In other words, we need the definition of draw() in the Shape class but do
not need the body. We can do the same by writing
• virtual void draw() { // Empty} • The same can also be achieved by writing
• virtual void draw() = 0; • Here, when we write ‘= 0’ in place of the function body, the
function is said to be pure virtual function
Prof. VARANG N. ACHARYA Asst. Prof. & Head
MCA Department
Parul Institute of Engineering & Technology
Vadodara
Phone : (02668) 260300, 260344
URL : http://sites.google.com/site/vnaclass/
Email : [email protected]
Pure Virtual Function …
• Pure virtual function has an important advantage
• It forces the native class to be abstract, and object of the
class cannot be created.
• In a way, when a programmer wants the user not to define
objects of a specific class, he can define a pure virtual
function (may be a dummy) inside the class.
Prof. VARANG N. ACHARYA Asst. Prof. & Head
MCA Department
Parul Institute of Engineering & Technology
Vadodara
Phone : (02668) 260300, 260344
URL : http://sites.google.com/site/vnaclass/
Email : [email protected]
//PureVirtualFunction.cpp
#include<iostream.h>
using namespace std;
class shape
{
int linestyle, fillcollor;
public:
virtual void draw()=0; // this is pure virtual function
virtual ~shape()
{
cout << "Shape destroyed ... "<<endl;
}
};
void shape::draw()
{
cout << "Shape is drawn \n";
}
class circle:public shape
{
int radius, centerpointx, centerpointy;
public:
~circle()
{
cout<<"Circle destroyed...\n";
}
void draw()
{
cout << "Circle is drawn \n";
}
};
void main()
{
// shape someshape; // error:cannot instantiate
// abstract class
shape *ptrshape;
circle ring;
// someshape.draw(); // not allowed
ptrshape->shape::draw(); //static call to shape draw
ptrshape = ˚
ptrshape->draw(); // this draws a circle
cout <<" Messages from destructor starts now\n\n";
ptrshape = new circle;
delete ptrshape; // if ~shape is not virtual, this won't
// work as expected
cout<<" Above messages are from delete \n\n";
cout<<"following messages are normal messages exiting
the program\n";
}
Output of the program
Shape is drawn
Circle is drawn
Messages from destructor starts now
Circle destroyed...
Shape destroyed ...
Above messages are from delete
following messages are normal messages exiting the program
Circle destroyed...
Shape destroyed ...
Prof. VARANG N. ACHARYA Asst. Prof. & Head
MCA Department
Parul Institute of Engineering & Technology
Vadodara
Phone : (02668) 260300, 260344
URL : http://sites.google.com/site/vnaclass/
Email : [email protected]
?