lab 10 oop
lab 10 oop
(LAB-10)
Reusability IV
Polymorphism in Object Oriented Programming
Lab 10: Polymorphism in Object Oriented
Programming
1. Introduction
In general, polymorphism means ‘various shapes’ and within the context of an object-oriented
programming (OOP) language, it is the ability of an object to acquire various forms while
referencing various instances of the different classes in inheritance hierarchy. In OOP, a
significant characteristic is the type compatibility of a derived class pointer to its base class
pointer. Taking advantage of this useful aspect, polymorphism establishes a new way of
programming.
A member function of a base class can be made a virtual function if it is probable to redefine
(override) this function in the derived class. The significance of making a function virtual
becomes evident when you want to invoke function of derived class from a pointer of base class
referencing derived class’s object. Following code provides an example of polymorphism
mechanism in C++.
class Base
{
public:
virtual void func()
{
cout<<”Base Class Function”;
}
};
Virtual keyword can also be used with destructors and classes. However, virtual keyword
possesses different meanings when used with destructor and classes as explained below.
Virtual Destructors:
In practice, it is always recommended to make the base class destructor as virtual. In the absence
of virtual keyword with base class destructor, upon deletion of any derived class’s object only
destructor of base class would be called.
class Base
{
protected:
void func()
{ cout<<”A Base Class Function”; }
};
class Derived1: public Base{ };
class Derived2: public Base{ };
class Derived3: public Derived1, public Derived2
{ };
In the code above, both (Derived1 and Derived2) classes contain a copy of func(), which is
inherited from class Base. Upon the invocation of func() with an object of Derived3 class,
compiler would be unable to decide which copy to use.
To overcome this situation, it is required to use virtual keyword with base class inheritance.
Hence, the above code would be implemented as
class Base
{
protected:
void func()
{ cout<<”A Base Class Function”; }
};
class Derived1: virtual public Base{ };
class Derived2: virtual public Base{ };
class Derived3: public Derived1, public Derived2
{ };
class Base
{
protected:
virtual void func() = 0;
};
Instantiation of an abstract class is not possible and you should override pure virtual function in
derived class(es).
3. Concept Map
Following encapsulation and inheritance, polymorphism is the third important capability of OOP
paradigm. The fundamental inspiration behind polymorphism is that of dynamic binding. In this
way, at compile time, compiler knows nothing about which function to call. On the contrary,
decision is made at runtime. Polymorphism helps programmer to make program in general rather
than specific. In simple words, it provides a single interface with different implementations.
Moreover, polymorphism facilitates program extensibility while permitting new derived classes
and functions to be added to an inheritance hierarchy without modifying application programs
that already utilize various interfaces of that inheritance hierarchy. However, for beginners, it is
difficult to grasp and implement the concept of polymorphism, dynamic binding, and abstract
classes.
LAB TASK
Task 1:
Consider an abstract class Animal having
A datamember “Name”
A datamember “Zoo”
A single function named show()
A class named Birds inherits Animal class and adds fields representing
A bool type variable flying
Override function named show() to display values of its all attributes
A class named Reptiles inherits BOOK class and adds fields representing
Length
Override function named show() to display values of its all attributes
#include <iostream>
#include <string>
using namespace std;
public:
Animal(string n, string z) : Name(n), Zoo(z) {}
public:
Reptiles(string n, string z, float l) : Animal(n, z), Length(l) {}
// Example usage
int main() {
Birds b("Parrot", "Lahore Zoo", 1);
Reptiles r("Crocodile", "Karachi Zoo", 5.2f);
Animal* a1 = &b;
Animal* a2 = &r;
a1->show();
cout << endl;
a2->show();
return 0;
}
Task 2
Create a class named Person, which contains
A pure virtual function named print()
Two data fields i.e. personName and age
A class named Student inherits Person class, which contains
Two data fields i.e. Std_id and Cgpa
Overridden function print() to display all details relevant to a patient
#include <iostream>
#include <string>
using namespace std;
public:
Person(string name, int a) : personName(name), age(a) {}
virtual ~Person() {}
};
public:
Student(string name, int a, int id, float c)
: Person(name, a), Std_id(id), Cgpa(c) {}
public:
Regular(string name, int a, int id, float c, string school, float fee)
: Student(name, a, id, c), SchoolName(school), Fee(fee) {}
// Example usage
int main() {
Regular r("Ali", 27,535004 , 3.92, "NUST", 250000);
Person* p = &r;
p->print();
return 0;
}
Task 3
#include <iostream>
using namespace std;
public:
// Constructor
Rectangle() : length(0), width(0) {}
// Mutators
void setLength(float l) {
length = l;
}
void setWidth(float w) {
width = w;
}
// Accessors
float getLength() {
return length;
}
float getWidth() {
return width;
}
// Main function
int main() {
// Create object dynamically
GeometricShape* shape = new Rectangle();
// Clean up
delete shape;
return 0;
}
Task 4
Testing
For Task 1, it is required to check the assignment of derived class instances to base class
pointer. Moreover, (while considering the dynamic binding) test the invocation of
respective show() function.
For Task 2, it is required to check the assignment of derived class instances to base class
pointer. Moreover, (while considering the dynamic binding) test the invocation of
respective print() function.
#include <iostream>
#include <string>
using namespace std;
//////////////////////////////////////////////////
// Task 1: Animal → Birds, Reptiles
//////////////////////////////////////////////////
// Abstract base class
class Animal {
protected:
string Name;
string Zoo;
public:
Animal(string name, string zoo) : Name(name), Zoo(zoo) {}
public:
Birds(string name, string zoo, bool isFlying)
: Animal(name, zoo), flying(isFlying) {}
public:
Reptiles(string name, string zoo, float len)
: Animal(name, zoo), Length(len) {}
//////////////////////////////////////////////////
// Task 2: Person → Student → Regular
//////////////////////////////////////////////////
public:
Person(string name, int a) : personName(name), age(a) {}
public:
Student(string name, int a, int id, float c)
: Person(name, a), Std_id(id), Cgpa(c) {}
public:
Regular(string name, int a, int id, float c, string school, float fee)
: Student(name, a, id, c), SchoolName(school), Fee(fee) {}
//////////////////////////////////////////////////
// Main Function: Demonstration of Dynamic Binding
//////////////////////////////////////////////////
int main() {
// ----- Task 1 -----
Animal* a1 = new Birds("Parrot", "Safari Zoo", true);
Animal* a2 = new Reptiles("Python", "City Zoo", 3.5);
delete a1;
delete a2;
delete p;
return 0;
}