Module 6:
Polymorphism
Prof. Tran Minh Triet
1
Acknowledgement
❖Slides
▪ Course CS202: Programming Systems
Instructor: MSc. Karla Fant,
Portland State University
▪ Course CS202: Programming Systems
Instructor: Dr. Dinh Ba Tien,
University of Science, VNU-HCMC
▪ Course DEV275: Essentials of Visual Modeling with
UML 2.0
IBM Software Group
2
Outline
❖IS-A relationship
❖Initialization of a pointer to base class
❖Static binding
❖Typecasting of a pointer to an object
❖Virtual functions and polymorphism
❖Pure virtual functions
❖Abstract class
3
IS-A relationship
❖Do not implement inheritance when you only
want to use some attributes or behaviors of
an existing class. Is it
logical?
❖The inheritance is only applied when there is
a “IS-A” relationship between classes
▪ E.g. Dog is an animal. Or, employer is an employee.
4
An example
❖Cat “is an” animal.
Animal
class Animal
{
...
};
Cat
class Cat: public Animal
{
...
};
5
A pointer to base class
❖A pointer to base class can be assigned with
the address of an object of the derived class.
❖For example:
Animal *pAni;
Cat c;
pAni = &c; //OK
6
Implicit type conversion in inheritance
❖It is normal to pass a derived class variable to
a function with an argument of base class
data type.
❖The compiler will do an implicit conversion.
Animal::Process(const Animal &a);
int main()
{
Cat c;
Animal::Process(c); //OK
} 7
Initialization of a pointer to base class
A* pA;
pA can be instantiated:
pA = new X(…);
where X is A or X is a class derived from A
8
Initialization of a pointer to base class
A* pA; A
pA = new A(…);
pA = new B(…); B
pA = new C(…);
C
9
Initialization of a pointer to base class
B* pB; A
pB = new A(…);
pB = new B(…); B
pB = new C(…);
C
10
Initialization of a pointer to base class
You are requested to create a polygon
CPolygon* pShape; Polygon
You can draw a triangle
pShape = new Triangle(…); Triangle Quadrilateral
or a quadrilateral
pShape = new Quadrilateral(…);
Rectangle
or a rectangle
pShape = new Rectangle(…);
11
Initialization of a pointer to base class
You are requested to create a quadrilateral
CQuadrilateral* pShape; Polygon
You can draw a rectangle
pShape = new Rectangle(…); Triangle Quadrilateral
or a quadrilateral
pShape = new Quadrilateral(…);
Rectangle
You cannot draw a triangle
pShape = new Triangle(…);
You cannot draw a general polygon (e.g. pentagon)
pShape = new Polygon(…); 12
Static binding
Consider the following situation: A
❖class A has void Print()
❖class B also has void Print()
❖class C has void Print() too B
int main() {
C varC;
B varB; C
varB.Print(); // Print() of B
varC.Print(); // Print() of C
varC.B::Print(); // Print() of B
} 13
Static binding
❖Another example: A
int main()
{
A varA;
B varB; B
var1 is formally a
C varC;
pointer to class A
A *var1, *var2;
var1 = &varC; var1 is actually pointed to C
an object of class C
var2 = &varB;
var1->Print(); // Print() of A
var2->Print(); // Print() of A
} 14
Typecasting of pointer to an object
Formally, pA is a pointer to an object of class A
A* pA;
Actually, pA is currently pointer to an object of
class X
pA = new X(…);
pA can be typecasted to a pointer to an object
of class Y where Y is X or Y is a base class of X
Y* pY;
pY = (Y*)pA;
15
Typecasting of pointer to an object
Polygon
Triangle Quadrilateral
Rectangle
pShape is formally a pointer to a quadrilateral
CQuadrilateral* pShape;
Actually, pShape is a pointer to a rectangle
pShape = new Rectangle(…);
16
Typecasting of pointer to an object
Polygon
Triangle Quadrilateral
pShape is currently pointed to a polygon Rectangle
Polygon* p = (Polygon*)pShape;
pShape is currently pointed to a rectangle
Rectangle* p = (Rectangle *)pShape;
17
Typecasting of pointer to an object
Polygon
Triangle Quadrilateral
Rectangle
We no longer need this object
delete pShape;
Now, pShape is re-instantiated as a pointer to a
quadrilateral
pShape = new Quadrilateral(…); 18
Typecasting of pointer to an object
Polygon
Triangle Quadrilateral
pShape is currently pointed to a polygon Rectangle
Polygon* p = (Polygon*)pShape;
We are not sure if pShape is currently pointed to a
rectangle
Rectangle* p = (Rectangle *)pShape;
19
Method invocation
pA -> F(…);
F(…) must be a member function of the
current formal type of pA
The actual behavior of F(…) should
correspond to the actual type of pA
20
Method Invocation
class Polygon class Quadrilateral :
{ public Polygon
public: {
double Surface(); public:
double Draw(); double Surface();
} double Draw();
}
class Triangle: class Rectangle:
public Polygon public Quadrilateral
{ {
public: public:
double Surface(); double Surface();
double Draw(); double Draw();
} } 21
Method Invocation
Polygon
Polygon myPolygon;
myPolygon.Draw();
Triangle Quadrilateral
Triangle myTriangle;
myTriangle.Draw(); Rectangle
Polygon* pPolygon;
pPolygon = new Triangle(…);
pPolygon->Draw();
22
Method Invocation
Polygon
Quadrilateral* pPolygon;
pPolygon = new Rectangle(…);
pPolygon->Draw(); Triangle Quadrilateral
…
// IN CLASS DEMO Rectangle
23
Virtual function
■ Static binding problem:
class Animal void doSomething(Animal
{ p)
public: {
Bind to Animal
void talk() { cout << “Don’t talk”; } p.talk(); implementation
}; } when compile
void main()
class Cat: public Animal {
{ Cat c;
public: Dog d;
void talk() { cout << “Meo meo”; } doSomething(c);
}; doSomething(d);
class Dog: public Animal Animal *p;
{ p = &c;
public: p->talk(); Bind to Animal
implementation
void talk() { cout << “Gau gau”; } p = &d;
when compile
}; p->talk();
} 24
Virtual function
■ Virtual function concept
■ Normal function
❑ Function call binds to implementation at compile-time.
🡺 Static binding.
■ Virtual function
❑ Function call binds to implementation at run-time .
🡺 Dynamic binding.
🡺 Implementation depends on run-time object.
■ C++ usage
❑ Declaration: virtual <Function signature>;
❑ Called through object pointer.
25
Virtual Method Invocation
class Polygon class Quadrilateral :
{ public Polygon
public: {
virtual double Surface(); public:
virtual double Draw(); virtual double Surface();
} virtual double Draw();
}
class Triangle: class Rectangle:
public Polygon public Quadrilateral
{ {
public: public:
virtual double Surface(); virtual double Surface();
virtual double Draw(); virtual double Draw();
} } 26
Virtual function
■ Dynamic binding
class Animal void doSomething(Animal *p)
{ {
public: p->talk(); implementation
virtual void talk() { cout << “Don’t talk”; }} depends on
}; void main() run-time
{ object
class Cat: public Animal Cat c;
{ Dog d;
public: doSomething(&c);
void talk() { cout << “Meo meo”; } doSomething(&d);
};
Animal *p;
class Dog: public Animal p = &c;
{ p->talk(); implementation
public: p = &d; depends on
void talk() { cout << “Gau gau”; } p->talk(); run-time
}; } object
27
Virtual function
■ Pure virtual function
■ Has declaration only, no implementation
■ virtual <Function signature> = 0
■ Used for dynamic binding
■ Derived class provides implementation
class Animal
{
public: Pure virtual function, has no implementation!!
virtual void talk() = 0;
};
28
Virtual function/operation
■ We sometimes declare a function, but we do not
implement it
class Shape {
For a general shape, we
protected: do not know how to
calculate area.
int m_Width;
int m_Height; A pure virtual function
has “= 0”
public:
virtual int getArea() = 0;
};
29
Virtual function
■ Example:
class Animal void doSomething(Animal *p)
Abstract class
{ {
public: p->talk(); implementation
virtual void talk() = 0; } depends on
}; void main() run-time
{ object
class Cat: public Animal Cat c;
{ Dog d;
public: doSomething(&c);
void talk() { cout << “Meo meo”; } doSomething(&d);
};
Animal *p;
class Dog: public Animal p = new Animal; // Wrong
{ p = new Cat; // Right
public: p->talk();
void talk() { cout << “Gau gau”; } }
};
30
Abstract class
■ An abstract class is a class having at least one
pure virtual function
❑ Pure virtual operation does not have implementation
■ An abstract class is called interface (in C++)
■ We cannot instantiate an object from an abstract
class
■ A concrete class is a class that can be
instantiated
■ A derived concrete class must implement virtual
functions from the base class
31
Abstract class example
class Shape { main() {
protected: Rectangle rect;
int m_Width; Triangle tri;
int m_Height; rect.setWidth(5);
public: rect.setHeight(7);
virtual int getArea() = 0;
}; tri.setWidth(5);
tri.setHeight(7);
class Rectangle : public Shape {
public: int getArea() { Shape shape; // wrong!
return (m_Width * m_Height); }
}
};
class Triangle: public Shape {
public: int getArea() {
return (m_Width * m_Height)/2;
}
};
32
Why do we need abstract
classes?
■ An abstract class provides a base class for
inheritance
■ Detailed implementation of one or many
operations is yet to know
■ Support polymorphism
33
Virtual destructor: problem
class Employee
{ void main()
private:
{
char *m_Name;
public:
Doctor *doc = new Doctor;
~Employee() { delete doc;
delete m_Name; Call order:
} ~Doctor()
}; ~Employee()
class Doctor : public Employee
{ Employee *e = new Doctor;
private: delete e;
char *m_Specialty; }
public:
~Doctor() { Call order:
~Employee()
delete m_Specialty;
}
}; Is there any problem
with this?
34
Virtual destructor: solution
class Employee
{ void main()
private:
{
char *m_Name;
public:
Doctor *doc = new Doctor;
~virtual Employee() { delete doc;
delete m_Name; Call order:
} ~Doctor()
}; ~Employee()
class Doctor : public Employee
{ Employee *e = new Doctor;
private: delete e;
char *m_Specialty; }
public:
Call order:
~Doctor() {
~Doctor()
delete m_Specialty; ~Employee()
}
};
35