When
a message can be processed in different ways is called polymorphism.
Polymorphism means many forms.
Polymorphism
is one of the fundamental concepts of OOP.
Polymorphism
provides following features:
- It allows you to invoke methods of derived class through base class reference during runtime.
- It has the ability for classes to provide different implementations of methods that are called through the same name.
Polymorphism
is of two types:
1.Compile
time polymorphism/Overloading
2. Runtime
polymorphism/Overriding
Compile
Time Polymorphism:
Compile time polymorphism is method and operators overloading. It is also called early binding.
In method overloading method performs the different task at the different input parameters.
Function overloading in C++:
You
can have multiple definitions for the same function name in the same
scope. The definition of the function must differ from each other by
the types and/or the number of arguments in the argument list. You
can not overload function declarations that differ only by return
type.
Following
is the example where same function print() is
being used to print different data types:
#include <iostream>
using namespace std;
class printData
{
public:
void print(int i) {
cout << "Printing int: " << i << endl;
}
void print(double f) {
cout << "Printing float: " << f << endl;
}
void print(char* c) {
cout << "Printing character: " << c << endl;
}
};
int main(void)
{
printData pd;
// Call print to print integer
pd.print(5);
// Call print to print float
pd.print(500.263);
// Call print to print character
pd.print("Hello C++");
return 0;
}
When
the above code is compiled and executed, it produces the following
result:
Printing int: 5
Printing float: 500.263
Printing character: Hello C++
Operators overloading in C++:
You
can redefine or overload most of the built-in operators available in
C++. Thus a programmer can use operators with user-defined types as
well.
Overloaded
operators are functions with special names the keyword operator
followed by the symbol for the operator being defined. Like any other
function, an overloaded operator has a return type and a parameter
list.
Box operator+(const Box&);
declares
the addition operator that can be used to add two
Box objects and returns final Box object. Most overloaded operators
may be defined as ordinary non-member functions or as class member
functions. In case we define above function as non-member function of
a class then we would have to pass two arguments for each operand as
follows:
Box operator+(const Box&, const Box&);
Following
is the example to show the concept of operator over loading using a
member function. Here an object is passed as an argument whose
properties will be accessed using this object, the object which will
call this operator can be accessed using this operator
as explained below:
#include <iostream>
using namespace std;
class Box
{
public:
double getVolume(void)
{
return length * breadth * height;
}
void setLength( double len )
{
length = len;
}
void setBreadth( double bre )
{
breadth = bre;
}
void setHeight( double hei )
{
height = hei;
}
// Overload + operator to add two Box objects.
Box operator+(const Box& b)
{
Box box;
box.length = this->length + b.length;
box.breadth = this->breadth + b.breadth;
box.height = this->height + b.height;
return box;
}
private:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
};
// Main function for the program
int main( )
{
Box Box1; // Declare Box1 of type Box
Box Box2; // Declare Box2 of type Box
Box Box3; // Declare Box3 of type Box
double volume = 0.0; // Store the volume of a box here
// box 1 specification
Box1.setLength(6.0);
Box1.setBreadth(7.0);
Box1.setHeight(5.0);
// box 2 specification
Box2.setLength(12.0);
Box2.setBreadth(13.0);
Box2.setHeight(10.0);
// volume of box 1
volume = Box1.getVolume();
cout << "Volume of Box1 : " << volume <<endl;
// volume of box 2
volume = Box2.getVolume();
cout << "Volume of Box2 : " << volume <<endl;
// Add two object as follows:
Box3 = Box1 + Box2;
// volume of box 3
volume = Box3.getVolume();
cout << "Volume of Box3 : " << volume <<endl;
return 0;
}
When
the above code is compiled and executed, it produces the following
result:
Volume of Box1 : 210
Volume of Box2 : 1560
Volume of Box3 : 5400
Overloadable/Non-overloadableOperators:
Following
is the list of operators which can be overloaded:
+
|
-
|
*
|
/
|
%
|
^
|
&
|
|
|
~
|
!
|
,
|
=
|
<
|
>
|
<=
|
>=
|
++
|
--
|
<<
|
>>
|
==
|
!=
|
&&
|
||
|
+=
|
-=
|
/=
|
%=
|
^=
|
&=
|
|=
|
*=
|
<<=
|
>>=
|
[]
|
()
|
->
|
->*
|
new
|
new []
|
delete
|
delete []
|
Following
is the list of operators, which can not be overloaded:
::
|
.*
|
.
|
?:
|
Operator Overloading Examples:
Here
are various operator overloading examples to help you in
understanding the concept.
S.N.
|
Operators and Example
|
---|---|
1
|
Unary operators overloading
|
2
|
Binary operators overloading
|
3
|
Relational operators overloading
|
4
|
Input/Output operators overloading
|
5
|
++ and -- operators overloading
|
6
|
Assignment operators overloading
|
7
|
Function call () operator overloading
|
8
|
Subscripting [] operator overloading
|
9
|
Class member access operator -> overloading
|
When
and why to use method overloading
Use
method overloading in situation where you want a class to be able to
do something, but there is more than one possibility for what
information is supplied to the method that carries out the task.
You
should consider overloading a method when you for some reason need a
couple of methods that take different parameters, but conceptually do
the same thing.
Runtime Time Polymorphism
Runtime time polymorphism is done using inheritance and virtual functions. Method overriding is called runtime polymorphism. It is also called late binding.
When overriding a method, you change the behavior of the method for the derived class. Overloading a method simply involves having another method with the same prototype.
Caution: Don't confused method overloading with method overriding, they are different, unrelated concepts. But they sound similar.
Method Overriding:
Whereas Overriding means
changing the functionality of a method without changing the
signature. We can override a function in base class by creating a
similar function in derived class. This is done by
usingvirtual/override keywords.
Base class method has to be marked with virtual keyword and we can override it in derived class usingoverride keyword.
Derived class method will completely overrides base class method i.e. when we refer base class object created by casting derived class object a method in derived class will be called.
Base class method has to be marked with virtual keyword and we can override it in derived class usingoverride keyword.
Derived class method will completely overrides base class method i.e. when we refer base class object created by casting derived class object a method in derived class will be called.
The word polymorphism means having many forms. Typically, polymorphism occurs when there is a hierarchy of classes and they are related by inheritance.
C++
polymorphism means that a call to a member function will cause a
different function to be executed depending on the type of object
that invokes the function.
Consider
the following example where a base class has been derived by other
two classes:
#include <iostream>
using namespace std;
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
int area()
{
cout << "Parent class area :" <<endl;
return 0;
}
};
class Rectangle: public Shape{
public:
Rectangle( int a=0, int b=0)
{
Shape(a, b);
}
int area ()
{
cout << "Rectangle class area :" <<endl;
return (width * height);
}
};
class Triangle: public Shape{
public:
Triangle( int a=0, int b=0)
{
Shape(a, b);
}
int area ()
{
cout << "Triangle class area :" <<endl;
return (width * height / 2);
}
};
// Main function for the program
int main( )
{
Shape *shape;
Rectangle rec(10,7);
Triangle tri(10,5);
// store the address of Rectangle
shape = &rec;
// call rectangle area.
shape->area();
// store the address of Triangle
shape = &tri;
// call triangle area.
shape->area();
return 0;
}
When
the above code is compiled and executed, it produces the following
result:
Parent class area
Parent class area
The
reason for the incorrect output is that the call of the function
area() is being set once by the compiler as the version defined in
the base class. This is called static resolution of
the function call, orstatic linkage - the function call
is fixed before the program is executed. This is also sometimes
calledearly binding because the area() function is set
during the compilation of the program.
But
now, let's make a slight modification in our program and precede the
declaration of area() in the Shape class with the keyword virtual so
that it looks like this:
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
virtual int area()
{
cout << "Parent class area :" <<endl;
return 0;
}
};
After
this slight modification, when the previous example code is compiled
and executed, it produces the following result:
Rectangle class area
Triangle class area
This
time, the compiler looks at the contents of the pointer instead of
it's type. Hence, since addresses of objects of tri and rec classes
are stored in *shape the respective area() function is called.
As
you can see, each of the child classes has a separate implementation
for the function area(). This is how polymorphism is
generally used. You have different classes with a function of the
same name, and even the same parameters, but with different
implementations.
Virtual Function:
A virtual function
is a function in a base class that is declared using the
keyword virtual. Defining in a base class a virtual
function, with another version in a derived class, signals to the
compiler that we don't want static linkage for this function.
What
we do want is the selection of the function to be called at any given
point in the program to be based on the kind of object for which it
is called. This sort of operation is referred to as dynamic
linkage, or late binding.
Pure Virtual Functions:
It's
possible that you'd want to include a virtual function in a base
class so that it may be redefined in a derived class to suit the
objects of that class, but that there is no meaningful definition you
could give for the function in the base class.
We
can change the virtual function area() in the base class to the
following:
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
// pure virtual function
virtual int area() = 0;
};
The
= 0 tells the compiler that the function has no body and above
virtual function will be called pure virtual function.
More
discuss about virtual function in virtual blog.