C++ Polymorphism
C++ Polymorphism
The word polymorphism means having many forms. In simple words, we can define
polymorphism as the ability of a message to be displayed in more than one form.
Polymorphism is one of the core concepts of Object-Oriented Programming (OOP).
It allows objects of different classes to be treated as objects of a common base class.
The term "polymorphism" means "many forms," and in C++, it enables the same
function or operator to behave differently based on the context.
Polymorphism is a feature of OOPs that allows the object to behave differently
in different conditions. In C++ we have two types of polymorphism:
1) Compile time Polymorphism – This is also known as static (or early) binding.
2) Runtime Polymorphism – This is also known as dynamic (or late) binding.
int main() {
Geeks obj1;
// Which function is called will depend on the
parameters passed
// The first 'func' is called
obj1.func(7);
#include <iostream>
class Math {
public:
int sum(int a, int b) {
return a + b;
}
int sum(int a, int b, int c) {
return a + b + c;
}
};
int main() {
Math obj;
cout << "Sum of 2 numbers: " << obj.sum(5, 10) << endl;
// Calls sum(int, int)
cout << "Sum of 3 numbers: " << obj.sum(5, 10, 15) << endl;
// Calls sum(int, int, int)
return 0;
}
2) Main Function:
The entry point of a C++ program, main(), cannot be overloaded. The C++
standard specifies that there should be only one main() function.
3) Member function declarations with the same name and the name parameter-
type-list cannot be overloaded if any of them is a static member function
declaration. For example, following program fails in compilation.
#include<iostream>
class Test {
static void fun(int i) {}
void fun(int i) {}
};
int main()
{
Test t;
getchar();
return 0;
}
• Operator Overloading:
C++ also provide option to overload operators. For example, we can make the
operator (‘+’) for string class to concatenate two strings. We know that this is the
addition operator whose task is to add two operands. So a single operator ‘+’ when
placed between integer operands , adds them and when placed between string
operands, concatenates them.
Example:
int main()
{
Complex c1(10, 5), c2(2, 4);
Complex c3 = c1 + c2; // An example call t"operator+"
c3.print();
}
• Output:
• 12 + i9
• In the above example the operator ‘+’ is overloaded. The operator ‘+’ is an addition
operator and can add two numbers(integers or floating point) but here the operator is
made to perform addition of two imaginary or complex numbers.
2. Runtime polymorphism:
This type of polymorphism is achieved by Function Overriding.
• Function overriding on the other hand occurs when a derived class has a definition
for one of the member functions of the base class. That base function is said to
be overridden. The function signature remains same but the working of the function
is altered to meet the needs of the derived class
What is Function Overriding in C++?
Function overriding is a type of polymorphism in which we redefine the member function
of a class which is inherited from its base class. The function signature remains same but
the working of the function is altered to meet the needs of the derived class. So, when we
call the function using its name for the parent object, the parent class function is
executed. But when we call the function using the child object, the child class version
will be executed.
Real-Life Example of Function Overriding
The best Real-life example of this concept is the Constitution of India. India took the
political code, structure, procedures, powers, and duties of government institutions and set
out fundamental rights, directive principles, and the duties of citizens of other countries and
implemented them on its own; making it the biggest constitution in the world.
Another Development real-life example could be the relationship between RBI(The
Reserve Bank of India) and Other state banks like SBI, PNB, ICICI, etc. Where the RBI
passes the same regulatory function and others follow it as it is.
Example 1:
#include <iostream>
class Base {
public:
void show() {
cout << "Base class show() function" << endl;
}
};
class Derived : public Base {
public:
void show() { // Function Overriding
cout << "Derived class show() function" << endl;
}
};
int main() {
Base b1;
B1.show();
Derived d;
d.show(); // Calls Derived class's show()
return 0;
}
Example 2:
#include <iostream>
class Base {
public:
void show() {
cout << "Base class show() function" << endl;
}
};
class Derived : public Base {
public:
void show() { // Function Overriding
cout << "Derived class show() function" << endl;
}
};
int main() {
Base *b;
Derived d;
b=&d;
b->show();
d.show(); // Calls Derived class's show()
return 0;
}
Output:
Base class show() function
Derived class show() function
Example 3:
#include <iostream>
class Base {
public:
virtual void show() {
cout << "Base class show() function" << endl;
}
};
class Derived : public Base {
public:
void show() { // Function Overriding
cout << "Derived class show() function" << endl;
}
};
int main() {
Base *b;
Derived d;
b=&d;
b->show();
d.show(); // Calls Derived class's show()
return 0;
}
Output:
Derived class show() function
Derived class show() function
Compile time (early binding) VS runtime (late binding) behavior of
Virtual Functions
// C++ program to illustrate concept of Virtual Functions
#include <iostream>
using namespace std;
class base {
public:
virtual void print() { cout << "print base class\n"; }
void show() { cout << "show base class\n"; }
};
int main()
{
base* bptr;
derived d;
bptr = &d;
return 0;
}
Output:
print derived class
show base class
Explanation: Runtime polymorphism is achieved only through a pointer (or
reference) of the base class type. Also, a base class pointer can point to the objects of
the base class as well as to the objects of the derived class. In the above code, the base
class pointer ‘bptr’ contains the address of object ‘d’ of the derived class.
Late binding (Runtime) is done in accordance with the content of the pointer (i.e.
location pointed to by pointer) and Early binding (Compile-time) is done according to
the type of pointer since the print() function is declared with the virtual keyword so it
will be bound at runtime (output is print derived class as the pointer is pointing to
object of derived class) and show() is non-virtual so it will be bound during compile
time (output is show base class as the pointer is of base type).
#include <iostream>
using namespace std;
// Base class
class Shape {
protected:
int length, width;
public:
// parameterized constructor
Shape(int l, int w)
{
length = l;
width = w;
}
int get_Area()
{
cout << "This is call to parent class area\n";
// Returning 1 in user-defined function means true
return 1;
}
};
// Derived class
class Square : public Shape {
public:
Square(int l = 0, int w = 0): Shape(l, w)
{}
int get_Area()
{
cout << "Square area: " << length * width << '\n';
return (length * width);
}
};
// Derived class
class Rectangle : public Shape {
public:
Rectangle(int l = 0, int w = 0): Shape(l, w)
{}
int get_Area()
{
cout << "Rectangle area: " << length * width
<< '\n';
return (length * width);
}
};
int main()
{
Shape* s;
return 0;
}
Output:
This is call to parent class area
This is call to parent class area
In the above example:
• We store the address of each child’s class Rectangle and Square object in s and
• Then we call the get_Area() function on it,
• Ideally, it should have called the respective get_Area() functions of the child
classes but
• Instead, it calls the get_Area() defined in the base class.
• This happens due to static linkage which means the call to get_Area() is getting
set only once by the compiler which is in the base class.
#include <fstream>
#include <iostream>
using namespace std;
class Shape {
public:
virtual void calculate()
{
cout << "Area of your Shape ";
}
// usage of virtual Destuctor to avoid memory leak
virtual ~Shape()
{
cout << "Shape Destuctor Call\n";
}
};
class Rectangle : public Shape {
public:
int width, height, area;
void calculate()
{
cout << "Enter Width of Rectangle: ";
cin >> width;
cout << "Enter Height of Rectangle: ";
cin >> height;
area = height * width;
cout << "Area of Rectangle: " << area << "\n";
}
int main() {
cout << "Enter elements for first matrix:" << endl;
CMatrix mat1;
cout << "Enter elements for second matrix:" << endl;
CMatrix mat2;
CMatrix sum = mat1.addMatrix(mat2);
cout << "Resultant matrix after addition:" << endl;
sum.displayMatrix();
return 0;
}