OOP Lab-13,14a
OOP Lab-13,14a
Instructor
Muhammad Faheem Saleem
Topics: Polymorphism
e.g the “ +” operator in c++ can perform two specific functions at two different scenarios i.e
when the “+” operator is used in numbers, it performs addition.
int a = 6;
int b = 6;
int sum = a + b; // sum =12
And the same “+” operator is used in the string, it performs concatenation.
string firstName = "Great ";
A real-life example of polymorphism is a person who at the same time can have different
characteristics. Like a man at the same time is a father, a husband and an employee. So the same
person exhibits different behavior in different situations. This is called polymorphism.
Polymorphism is considered as one of the important features of Object-Oriented Programming.
Types:
1) Compile time Polymorphism – This is also known as static (or early) binding.
Compile-time polymorphism:
This type of polymorphism is achieved by function overloading or operator overloading.
Function Overloading: When there are multiple functions with the same name but different
parameters, then the functions are said to be overloaded. Functions can be overloaded by changing
the number of arguments or/and changing the type of arguments.
Operator Overloading: C++ also provides the option to overload operators. For example, we can
make use of the addition operator (+) for string class to concatenate two strings. We know that the
task of this operator is to add two operands. So a single operator ‘+’, when placed between integer
operands, adds them and when placed between string operands, concatenates them.
Runtime Polymorphism
In a Runtime polymorphism, functions are called at the time the program execution. Hence, it is
known as late binding or dynamic binding.
a. Virtual Functions
A virtual function is a member function which is declared within a base class and is
redefined (overridden) by a derived class. When you refer to a derived class object using a
pointer or a reference to the base class, you can call a virtual function for that object and
execute the derived class’s version of the function.
- Virtual functions ensure that the correct function is called for an object, regardless of the
type of reference (or pointer) used for function call.
- They are mainly used to achieve Runtime polymorphism
- Functions are declared with a virtual keyword in base class.
- The resolving of function call is done at runtime.
#include<iostream>
using namespace std;
class base {
public:
virtual void print()
{
cout << "print base class\n";
}
void show()
{
cout << "show base class\n";
}
};
class derived : public base {
public:
void print()
{
cout << "print derived class\n";
}
void show()
{
cout << "show derived class\n";
}
};
int main()
{
base *bptr;
derived d;
bptr = &d;
return 0;
}
Output:
print derived class show
base class
Example:
#include <iostream>
using namespace std;
class Animal {
public:
virtual void sound() {
cout << "This is a generic animal sound." << endl;
}
};
int main() {
Animal* a;
Dog d;
a = &d;
a->sound(); // Output: Dog barks!
return 0;
}
Explanation: The virtual function 'sound()' is overridden in the Dog class. The base class pointer calls the
derived class version at runtime.
Virtual means existing in appearance but not in reality. When virtual functions are used, a
program that appears to be calling a function of one class may in reality be calling a
function of a different class.
Why are virtual functions needed? Suppose you have a number of objects of different
classes but you want to put them all in an array and perform a particular operation on them
using the same function call. For example, suppose a
graphics program includes several different shapes: a triangle, a ball, a square, and so on .
Each of these classes has a member function draw() that causes the object to be drawn on
the screen.
Now suppose you plan to make a picture by grouping a number of these elements together,
and you want to draw the picture in a convenient way. One approach is to create an array
that holds pointers to all the different objects in the picture. The array might be defined
like this: shape* ptrarr[100]; // array of 100 pointers to shapes If you insert pointers to all
the shapes into this array, you can then draw an entire picture using a simple loop:
ptrarr[j]->draw();
This is an amazing capability: Completely different functions are executed by the same
function call. If the pointer in ptrarr points to a ball, the function that draws a ball is
called; if it points to a triangle, the triangle-drawing function is called. This is called
polymorphism, which means different forms. The functions have the same appearance,
the draw() expression, but different actual functions are called, depending on the contents
of ptrarr[j]. Polymorphism is one of the key features of object-oriented programming,
after classes and inheritance. For the polymorphic approach to work, several conditions
must be met. First, all the different classes of shapes, such as balls and triangles, must be
descended from a single base class (called shape in MULTSHAP). Second, the draw()
function must be declared to be virtual in the base class.
Slower: The function call takes slightly longer due to the virtual mechanism and makes it more
difficult for the compiler to optimize because it does not know exactly which function is going to
be called at compile time.
Difficult to Debug: In a complex system, virtual functions can make it a little more difficult to
figure out where a function is being called from.
#include <iostream>
using namespace std;
// Base class
class Vehicle { public:
// Virtual function
virtual void sound() {
cout << "Vehicle makes a sound" << endl;
}
};
// Derived class
class Car : public Vehicle {
public:
// Override sound() in Car class
void sound() override {
cout << "Car honks" << endl;
}
};
int main() {
// Create object of derived class
Car car;
return 0; }
We define a base class Vehicle with a virtual function sound(), representing the sound made by a
vehicle. We define a derived class Car that inherits from Vehicle. In the Car class, we override the
sound() function with our own implementation that represents the sound of a car, "Car honks". In
the main() function, we create an object car of the Car class. We call the sound() function on the
car object. Since sound() is declared as virtual in the base class and overridden in the derived class,
the version of sound() specific to the Car class is invoked, resulting in "Car honks" being printed.
#include <bits/stdc++.h>
using namespace std;
void show ()
{ cout<< "show base class" <<endl; }
};
void show ()
{ cout<< "show derived class" <<endl; }
};
//main function
int main()
{
base *bptr;
derived d; bptr =
&d;
return 0;
}
Output:
The base class base defines two member functions: print() and show(), with print() declared as
virtual. The derived class derived inherits from base and overrides the print() function with its own
implementation. In the main() function, a pointer of type base is assigned the address of a derived
class object. When calling bptr->print(), the overridden print() function of the derived class is
invoked due to dynamic binding, displaying "print derived class". However, bptr->show() calls the
show() function of the base class, as it's not virtual, resulting in "show base class" being printed.
This demonstrates how function overriding and virtual functions enable runtime polymorphism,
allowing for flexible and dynamic behavior in object-oriented programming.
class Animal {
public:
void sound() {
cout << "Generic animal sound." << endl;
}
};
int main() {
Animal* a;
Cat c;
a = &c;
a->sound(); // Output: Generic animal sound.
return 0;
}
Explanation: Without using virtual, the base class function is called even though the object is of the
derived class.
Lab Tasks:
1. Create a class hierarchy for employees where the base class has a virtual function 'calculateSalary()'.
Override this function in derived classes like Manager and Developer to display role-specific salary
information.
2. Implement a base class 'Appliance' with a virtual function 'operate()'. Create two derived classes 'Fan'
and 'AC'. Demonstrate polymorphism by calling the overridden function through a base class pointer.