C++ Polymorphism
The term "Polymorphism" is the combination of "poly" + "morphs"
which means many forms. It is a greek word. In object-oriented
programming, we use 3 main concepts: inheritance, encapsulation, and
polymorphism.
Real Life Example Of Polymorphism
Let's consider a real-life example of polymorphism. A lady behaves like
a teacher in a classroom, mother or daughter in a home and customer in
a market. Here, a single person is behaving differently according to the
situations.
Like we specified in the previous chapter; Inheritance lets us inherit
attributes and methods from another class. Polymorphism uses those
methods to perform different tasks. This allows us to perform a single
action in different ways.
For example, think of a base class called Animal that has a method
called animalSound(). Derived classes of Animals could be Pigs, Cats,
Dogs, Birds - And they also have their own implementation of an animal
sound (the pig oinks, and the cat meows, etc.):
Example
// Base class
class Animal {
public:
void animalSound() {
cout << "The animal makes a sound \n" ;
}
};
// Derived class
class Pig : public Animal {
public:
void animalSound() {
cout << "The pig says: wee wee \n" ;
}
};
// Derived class
class Dog : public Animal {
public:
void animalSound() {
cout << "The dog says: bow wow \n" ;
}
};
Remember from the Inheritance chapter that we use the : symbol to
inherit from a class.
Now we can create Pig and Dog objects and override
the animalSound() method:
Example
// Base class
class Animal {
public:
void animalSound() {
cout << "The animal makes a sound \n" ;
}
};
// Derived class
class Pig : public Animal {
public:
void animalSound() {
cout << "The pig says: wee wee \n" ;
}
};
// Derived class
class Dog : public Animal {
public:
void animalSound() {
cout << "The dog says: bow wow \n" ;
}
};
int main() {
Animal myAnimal;
Pig myPig;
Dog myDog;
myAnimal.animalSound();
myPig.animalSound();
myDog.animalSound();
return 0;
}
Try it Yourself »
Why And When To Use "Inheritance" and "Polymorphism"?
- It is useful for code reusability: reuse attributes and methods of an
existing class when you create a new class.
Polymorphism is considered as one of the important features of Object
Oriented Programming.
In C++ polymorphism is mainly divided into two types:
Compile time Polymorphism
Runtime Polymorphism
There are two types of polymorphism in C++:
1. Compile Time Polymorphism
In compile-time polymorphism, a function is called at the time of
program compilation. We call this type of polymorphism as early
binding or Static binding.
Function overloading and operator overloading is the type of Compile
time polymorphism.
I. Function Overloading
Function overloading means one function can perform many tasks. In
C++, a single function is used to perform many tasks with the same
name and different types of arguments. In the function overloading
function will call at the time of program compilation. It is an example
of compile-time polymorphism.
1. /*datatype functionname(<parameters>)
2. {
3. ...
4. }
5.
6. datatype samefunctionname(< different parameters/different number of
parameters >)
7. {
8. ...
9. }
10. */
In the below example, A function ADD() is used to perform two tasks.
The two asks would be to add two integer values and add two strings
(concatenate).
Readability of the program increases by function overloading. It is
achieved by using the same name for the same action.
Source Code:
1 #include <iostream>
2 class Addition {
3 public:
4 int ADD(int X,int Y) // Function with parameter
5 {
6 return X+Y; // this function is performing addition of two Integer value
7 }
8 int ADD() { // Function with same name but without parameter
9 string a= "HELLO";
10 string b="SAM"; // in this function concatenation is performed
11 string c= a+b;
12 cout<<c<<endl;
13
14 }
15 };
16 int main(void) {
17 Addition obj; // Object is created
18 cout<<obj.ADD(128, 15)<<endl; //first method is called
19 obj.ADD(); // second method is called
20 return 0;
21 }
22
Output
143
Operator Overloading
Operator overloading means defining additional tasks to operators
without changing its actual meaning. We do this by using operator
function.
The purpose of operator overloading is to provide a special meaning to
the user-defined data types.
Syntax for C++ Operator Overloading
To overload an operator, we use a special operator function. We define the
function inside the class or structure whose objects/variables we want the
overloaded operator to work with.
class className {
... .. ...
public
returnType operator symbol (arguments) {
... .. ...
}
... .. ...
};
Here,
returnType is the return type of the function.
operator is a keyword.
symbol is the operator we want to overload. Like: + , < , - , ++ , etc.
arguments is the arguments passed to the function.
Operator Overloading in Unary Operators
Unary operators operate on only one operand. The increment operator ++ and
decrement operator -- are examples of unary operators.
Example1: ++ Operator (Unary Operator) Overloading
// Overload ++ when used as prefix
#include <iostream>
using namespace std;
class Count {
private:
int value;
public:
// Constructor to initialize count to 5
Count() : value(5) {}
// Overload ++ when used as prefix
void operator ++ () {
++value;
}
void display() {
cout << "Count: " << value << endl;
}
};
int main() {
Count count1;
// Call the "void operator ++ ()" function
++count1;
count1.display();
return 0;
}
Run Code
Output
Count: 6
Here, when we use ++count1; , the void operator ++ () is called. This increases
the value attribute for the object count1 by 1.
Note: When we overload operators, we can use it to work in any way we like.
For example, we could have used ++ to increase value by 100.
However, this makes our code confusing and difficult to understand. It's our
job as a programmer to use operator overloading properly and in a consistent
and intuitive way.
The above example works only when ++ is used as a prefix. To make ++ work
as a postfix we use this syntax.
void operator ++ (int) {
// code
}
Notice the int inside the parentheses. It's the syntax used for using unary
operators as postfix; it's not a function parameter.
The advantage of Operators overloading is to perform different
operations on the same operand.
2. 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.
Function overriding is a part of runtime polymorphism. In function
overriding, more than one method has the same name with different
types of the parameter list.
It is achieved by using virtual functions and pointers. It provides slow
execution as it is known at the run time. Thus, It is more flexible as all
the things executed at the run time.
I. Function overriding
In function overriding, we give the new definition to base class
function in the derived class. At that time, we can say the base
function has been overridden. It can be only possible in the „derived
class‟. In function overriding, we have two definitions of the same
function, one in the superclass and one in the derived class. The
decision about which function definition requires calling happens
at runtime. That is the reason we call it „Runtime polymorphism‟.
Source code
1 #include <iostream>
2 using namespace std;
3 class Animal {
4 public:
5 void function(){
6 cout<<"Eating..."<<endl;
7 }
8 };
9 class Man: public Animal
10 {
11 public:
12 void function()
13 {
14 cout<<"Walking ..."<<endl;
15 }
16 };
17 int main(void) {
18 Animal A =Animal();
19 A.function(); //parent class object
20 Man m = Man();
21 m.function(); // child class object
22
23 return 0;
24 }
Output
Eating …..
Walking……
II. Virtual Function
A virtual function is declared by keyword virtual. The return type of
virtual function may be int, float, void.
A virtual function is a member function in the base class. We can
redefine it in a derived class. It is part of run time polymorphism. The
declaration of the virtual function must be in the base class by using
the keyword virtual. A virtual function is not static.
The virtual function helps to tell the compiler to perform dynamic
binding or late binding on the function.
If it is necessary to use a single pointer to refer to all the different
classes‟ objects. This is because we will have to create a pointer to the
base class that refers to all the derived objects.
But, when the base class pointer contains the derived class address,
the object always executes the base class function. For resolving this
problem, we use the virtual function.
When we declare a virtual function, the compiler determines which
function to invoke at runtime.
Let‟s see the below example for understanding how the program
execution happens without virtual function and with virtual function.
Source code
1 //without virtual Function
2
3 #include <iostream>
4 using namespace std;
5 class Add
6 {
7 int x=5, y=20;
8 public:
9 void display() //overridden function
10 {
11 cout << "Value of x is : " << x+y<<endl;
12 }
13 };
14 class Substract: public Add
15 {
16 int y = 10,z=30;
17 public:
18 void display() //overridden function
19 {
20 cout << "Value of y is : " <<y-z<<endl;
21 }
22 };
23 int main()
24 {
25 Add *m; //base class pointer .it can only access the base class members
26 Substract s; // making object of derived class
27 m = &s;
28 m->display(); // Accessing the function by using base class pointer
29 return 0;
30 }
Output
Value of x is: 25
Virtual Function used to invoke the derived class in a program.
Source Code
1 #include<iostream>
2 using namespace std;
4 class Add
5 {
6 public:
7 virtual void print ()
8 { int a=20, b=30;
9 cout<< " base class Action is:"<<a+b <<endl;
10 }
11
12 void show ()
13 { cout<< "show base class" <<endl; }
14 };
15
16 class Sub: public Add
17 {
18 public:
19 void print () //print () is already virtual function in derived class, we could als
20 { int x=20,y=10;
21
22 cout<< " derived class Action:"<<x-y <<endl; }
23
24 void show ()
25 { cout<< "show derived class" <<endl; }
26 };
27
28 //main function
29 int main()
30 {
31 Add *aptr;
32 Sub s;
33 aptr = &s;
34
35 //virtual function, binded at runtime (Runtime polymorphism)
36 aptr->print();
37
38 // Non-virtual function, binded at compile time
39 aptr->show();
40
41 return 0;
42 }
Output
derived class Action:10
show base class
Pure Virtual Function
When the function has no definition, we call such functions as “Do-
nothing function or Pure virtual function”. The declaration of this
function happens in the base class with no definition.
Source Code
1 #include <iostream>
2 using namespace std;
3 class Animal
4 {
5 public:
6 virtual void show() = 0; //Pure virtual function declaration.
7 };
8 class Man: public Animal
9 {
10 public:
11 void show()
12 {
13 cout << "Man is the part of animal husbandry " << endl;
14 }
15 };
16 int main()
17 {
18 Animal *aptr; //Base class pointer
19 //Animal a;
20 Man m; //derived class object creation.
21 aptr = &m;
22 aptr->show();
23 return 0;
24 }
Output
Man is the part of animal husbandry
Difference between run-time and compile-time
Run-time
1)Run time is the time period where the executable code is running.
2)Errors can be detected only after the execution of the program.
3)Errors that occur during the execution of a program are called run-time errors. Run
detected by the compiler.