Polymorphism allows objects of derived classes to be treated as the base class. This allows the same code to work with different object types through virtual functions. It reduces code duplication and improves maintainability. Polymorphism is demonstrated through an Employee class hierarchy where Manager and Clerical classes inherit from Employee but define their own behaviors. A list of Employees can be iterated over and treated the same due to polymorphism.
2. Introduction
• The last of the three fundamental pillars of object
orientation is the principle of polymorphism.
• It’s also the most abstract and difficult to initially see the benefits of.
• In the C++ model of polymorphism, it is inextricably tied
up in the idea of inheritance.
• They go together, hand in hand.
3. Polymorphism
• The word Polymorphism comes from the Greek.
• Poly meaning ‘parrot’
• Morph meaning ‘small man made of plasticine’.
• In basic terms, it means:
• To treat a specialised object as an instance of its more general
case.
• For example, a Circle is a Circle.
• But in a more general way, it’s also a shape.
4. The Scenario
• We’re going to explore the topic of polymorphism through
a simple example program.
• It relates to the relationship between two classes – an Employee
and a Manager.
• They are very similar except:
• Managers can hire and fire
• Employees cannot.
5. The Employee Class
class Employee {
private:
int payscale;
public:
int query_payscale();
void set_payscale (int p);
bool can_hire_and_fire();
};
#include "Employee.h"
bool Employee::can_hire_and_fire(){
return false;
}
void Employee::set_payscale(int val) {
payscale = val;
}
int Employee::query_payscale() {
return payscale;
}
6. The Manager Class
class Manager : public Employee {
public:
bool can_hire_and_fire();
};
#include "Manager.h"
bool Manager::can_hire_and_fire() {
return true;
}
7. The Program
#include <iostream>
#include "Employee.h"
#include "Manager.h"
using namespace std;
int main(int argc, char** argv) {
Employee *emp = new Employee();
Manager *man = new Manager();
cout << "Employees hiring and firing rights:" << emp-
>can_hire_and_fire() << endl;
cout << "Managerss hiring and firing rights:" << man-
>can_hire_and_fire() << endl;
return 1
}
8. The Output
• So far, it’s pretty straightforward.
• Output for employees is 0.
• False
• Output for managers is 1.
• True.
• So it is written, so shall it be.
• The polymorphism comes in when when we want to do something
a little more arcane.
• Make a pointer to a base class point to am object of a more specialised
class.
9. Polymorphism
#include <iostream>
#include "Employee.h"
#include "Manager.h"
using namespace std;
int main(int argc, char** argv) {
Employee *emp = new Employee();
Manager *man = new Manager();
Employee *poly = new Manager();
cout << "Employees hiring and firing rights:" << emp->can_hire_and_fire() <<
endl;
cout << "Managers hiring and firing rights:" << man->can_hire_and_fire() <<
endl;
cout << "Polymorphic hiring and firing rights:" << poly-
>can_hire_and_fire() << endl;
return 1;
}
10. And…?
• What happens now?
• In Java, it calls the most specialised version of the method.
• It would call the one defined in Manager.
• In C++, it calls the method as defined in the class that is referenced
by the pointer.
• It would call the one defined in Employee.
• Okay, great – but so what?
11. The Power
• The power comes from when we have many different
classes that extend from a common core.
• Rather than coding special conditions for each of them, we code for
the base class.
• This greatly reduces the amount of work that a developer
has to do.
• And properly distributes the responsibility for implementing
functionality.
12. Virtual Functions
• However, much of this is based on the idea that we can
trust a generalised reference to execute the most
appropriate method.
• As is done in Java
• C++ requires us to define a function as virtual if we want
this behaviour.
• From this point on, it becomes a virtual function and behaves in
the way we would expect from Java.
13. Modified Class Definition
class Employee {
private:
int payscale;
public:
int query_payscale();
void set_payscale (int p);
virtual bool can_hire_and_fire();
};
14. How Do Virtuals Work?
• When an object is created from a class, C++ creates a lookup
table for virtual functions.
• This is in addition to all other data stored.
• Each virtual function has an entry in this table.
• When you create the object with new, the entry is updated with a
reference to the appropriately specialized implementation.
• Each virtual method you declare increases the size of this
table.
• And thus size of the objects and processing time.
16. Modified Scenario
• Two classes stem from the same root.
• Employee
• Using the Power of Polymorphism, we can treat them as
instances of the base class.
• We can manipulate them as if they were just Employees.
• This means that we can’t make use of methods defined in the
specialised classes.
• Only what we can guarantee is implemented by virtue of the class
hierarchy.
18. The Employee Class
• The Employee class is now something we don’t really
want people using it.
• It’s a common core, not a fully fledged object in its own right.
• In the next lecture, we’ll look at how we can prevent
people making use of it directly.
• We’ll also look at ways other than inheritance to provide a structure
for objects.
19. Benefits of Polymorphism
• One of the benefits that comes from polymorphism is the
ease of processing lists of objects.
• We don’t need a separate queue for Managers and Clerical staff
• We just need one queue of employees
• We can iterate over each of these, provided we are
making use of base functions.
20. Benefits of Polymorphism
using namespace std;
void set_payscale (Employee* emp, float amount) {
emp->set_payscale (amount);
}
int main(int argc, char** argv) {
Employee *emp = new Employee();
Employee **emps = new Employee*[2];
emps[0] = new Manager();
emps[1] = new Clerical();
for (int i = 0; i < 2; i++) {
set_payscale (emps[i], 20000.0);
cout << "Payscale for " << i << " is " << emps[i]->query_payscale() << endl;
}
return 1;
}
21. Benefits of Polymorphism
• Polymorphism manages the complexity of the inheritance
model and lets you provide custom handling in the classes
themselves.
• You don’t need:
• if (it’s a manager) { do_this(); } else if (it’s a clerical) {
do_this_other_thing() }
• One method, properly designed, can handle all the heavy
lifting.
• This does require the use of a clean, well designed object hierarchy.
22. Summary
• Polymorphism is the last of the three pillars of object
oriented programming.
• The most powerful, but also the most abstract.
• You’re not really expected to ‘get it’ just yet.
• We’ll return to the topic in later lectures.
• In the next lecture we’re going to continue discussing
some of the ways in which we can enforce structure on
our unruly objects.