Polymorphism
Polymorphism
Lecture
Polymorphism
& Related Concepts
Polymorphism
Technical Definition
“ Polymorphism can be achieved through Dynamic binding.
binding.
Dynamic binding is enabled when a virtual function
function isis invoked
invoked
through
through aa derived
derived class object which is referred
referred indirectly
indirectlyby by
either a base class pointer
pointer or reference ””
or reference
Pointers to the base class of derived objects
Pointers to the base class of derived objects
class Parent {
• Inheritance implies an is-a relationship public:
between two classes void Hello() { cout << "Hi from a Parent!\n"; }
// ...
};
int main() {
Parent* P;
• C++ allow to set a Base pointer or reference Note: P can only calls
Child C;
to a Derived object. those members which
P = &C;
P->Hello(); are part of Parent class
}
Static binding vs. Dynamic Binding
Static binding (Compile-time binding )
•Example:
#include <iostream>
using namespace std;
In C++, all non-virtual functions are
void sayHi() bound at compile-time (static).
{ However, virtual functions can
cout << "Hello, World!\n"; have dynamic binding
}
int main()
{
sayHi();}
Dynamic binding ( Run-time binding )
class Parent {
• A virtual function is a member public:
function that you expect to be virtual void Hello() { cout << "Hi from a
redefined in derived classes. Parent!\n"; }
// ...
};
• If the member function definition is outside the class, the keyword virtual must not
be specified again.
class Parent {
public:
virtual void sayHi();
};
virtual void Parent::sayHi() { // error
cout << "Just hi!\n";
}
int main() {
Parent obj;
obj.print();
}
• A virtual function can be inherited from a base class by a derived class, like
other class member functions.
class Parent {
public: int main() {
virtual void print() { cout << "Hello!\n"; Child obj;
} obj.print();
}; }
class Child : public Parent {};
Virtual Function
• To let derived classes have their own implementation for the virtual function, we
override base class virtual functions in derived class.
• In order for a derived class virtual function instance to override the base class virtual
function instance, its signature must match the base class virtual function exactly.
class Parent
{
public: int main() {
virtual void sayHi() { cout << "Just hi!\n"; } Parent* p;
}; int choice;
cout << "1 -parent, 2 – child_1, 3 –child_2\n ";
cin >> choice;
class Child_1 : public Parent
{ switch (choice)
public: {
virtual void sayHi() { cout << "Hi from a case 1: p = new Parent; break;
Child_1!\n"; } case 2: p = new Child_1; break;
}; case 3: p = new Child_2; break;
}
p->sayHi(); // dynamic binding of sayHi()
class Child_2 : public Parent delete p;
{ }
public:
virtual void sayHi() { cout << "Hi from a
Child_2!\n"; }
};
Example
class Parent
{
public: int main() {
virtual void sayHi() { cout << "Just hi!\n"; } Parent* p;
}; int which;
cout << "1 -shape, 2 -triangle, 3 -rectangle\n ";
class Child_1 : public Parent cin >> which;
{ switch (which)
public:
Polymorphism is thus implemented by virtual functions
{
and run-time binding mechanism in C++. A class is
virtual void sayHi() { cout << "Hi from a case 1: p = new Parent; break;
case 2: p = new Child_1; break;
Child_1!\n"; }
}; called polymorphic if it contains virtual functions.
case 3: p = new Child_1; break;
}
class Child_2 : public Parent p->sayHi(); // dynamic binding of sayHi()
{ delete p;
public: }
virtual void sayHi() { cout << "Hi from a
Child_2!\n"; }
};
Polymorphism
• The first class that defines a virtual function is the base class
• A class with virtual member functions has a virtual table which contains the
address of its virtual functions.
• An object of such a class has a pointer(vptr) to point to the virtual table of
the class.
• Dynamic binding is done by looking up the virtual table for the entry point of
the appropriate function at run-time.
Virtual Functions
• A destructor can be virtual. Virtual destructors are very useful when some
derived classes have cleanup code.
• Example
class B {
public:
virtual B(); // error
virtual ~B(); // ok
virtual void f(); // ok
};
Dynamic v.s. Static binding
• Use compile-time binding when you are sure that any derived class
will not want to override the function dynamically.
• Use run-time binding when the derived class may be able to provide a
different implementation that should be selected at run-time.
Pure Virtual Function
• A class that has a pure virtual function is an abstract class. Abstract class
is used as an interface for its derived classes.
• If a class derived from an abstract class, and this class doesn’t override all
the pure virtual function in the base class, then this class is also an
abstract class.