Polymorphism
Polymorphism
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.
Real life example of polymorphism, a person at the same time can have
different characteristic. Like a man at the same time is a father, a husband, an
employee. So the same person posses different behavior in different
situations. This is called polymorphism.
Polymorphism is considered as one of the important features of Object
Oriented Programming.
Geeks obj1;
// Which function is called will depend on the parameters passed
// The first 'func' is called
obj1.func(7);
// The second 'func' is called
obj1.func(9.132);
// The third 'func' is called
obj1.func(85,64);
return 0;
}
Rules of Function Overloading
#include<iostream>
int foo() {
return 10;
}
char foo() {
return 'a';
}
int main()
{
char x = foo();
getchar();
return 0;
}
2) 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;
}
3) Parameter declarations that differ only in a pointer * versus an array [] are
equivalent. That is, the array declaration is adjusted to become a pointer
declaration. Only the second and subsequent array dimensions are significant
in parameter types. For example, following two function declarations are
equivalent.
#include<iostream>
#include<stdio.h>
int f ( int x) {
return x+10;
}
int main() {
getchar();
return 0;
}
Only the const and volatile type-specifiers at the outermost level of the
parameter type specification are ignored in this fashion; const and volatile
type-specifiers buried within a parameter type specification are significant and
can be used to distinguish overloaded function declarations. In particular, for
any type T,
“pointer to T,” “pointer to const T,” and “pointer to volatile T” are considered
distinct parameter types, as are “reference to T,” “reference to const T,” and
“reference to volatile T.” For example, see the example in this comment posted
by Venki.
6) Two parameter declarations that differ only in their default arguments are
equivalent. For example, following program fails in compilation with
error “redefinition of `int f(int, int)’ “
#include<iostream>
#include<stdio.h>
int main() {
getchar();
return 0;
}
class Complex {
private:
int real, imag;
public:
Complex(int r = 0, int i =0) {real = r; imag = i;}
// This is automatically called when '+' is used with
// between two Complex objects
Complex operator + (Complex const &obj) {
Complex res;
res.real = real + obj.real;
res.imag = imag + obj.imag;
return res;
}
void print() { cout << real << " + i" << imag << endl; }
};
int main()
{
Complex c1(10, 5), c2(2, 4);
Complex c3 = c1 + c2; // An example call to "operator+"
c3.print();
}
Output:
12 + i9
... .. ...
public
... .. ...
... .. ...
};
28. Count: 6
#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;
}
private:
double length; // Length of a box
double breadth; // Breadth of a box
double height; // Height of a box
};
// 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;
// volume of box 3
volume = Box3.getVolume();
cout << "Volume of Box3 : " << volume <<endl;
return 0;
}
Virtual Function in C++
A virtual function a member function which is declared within a base class and is re-
defined (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 Run-time.
Rules for Virtual Functions
1. Virtual functions cannot be static and also cannot be a friend function of another class.
2. Virtual functions should be accessed using pointer or reference of base class type to
achieve run time polymorphism.
3. The prototype of virtual functions should be same in base as well as derived class.
4. They are always defined in base class and overridden in derived class. It is not
mandatory for derived class to override (or re-define the virtual function), in that case
base class version of function is used.
5. A class may have virtual destructor but it cannot have a virtual constructor.
Compile-time(early binding) VS run-time(late binding) behavior of Virtual
Functions
Consider the following simple program showing run-time behavior of virtual
functions.
// CPP program to illustrate
#include<iostream>
class base
public:
void show ()
};
public:
void print ()
void show ()
};
int main()
base *bptr;
derived d;
bptr = &d;
bptr->print();
Output:
print derived class
show base class
#include<iostream>
class base
public:
};
public:
};
int main()
base *p;
derived obj1;
p = &obj1;
// in base
p->fun_1();
p->fun_2();
p->fun_3();
p->fun_4();
// derived class
//p->fun_4(5);
}
Output:
base-1
derived-2
base-3
base-4
Explanation: Initially, we create a pointer of type base class and initialize it with the
address of the derived class object. When we create an object of the derived class,
the compiler creates a pointer as a data member of the class containing the address
of VTABLE of the derived class.
Similar concept of Late and Early Binding is used as in above example. For fun_1()
function call, base class version of function is called, fun_2() is overridden in derived
class so derived class version is called, fun_3() is not overridden in derived class
and is virtual function so base class version is called, similarly fun_4() is not
overridden so base class version is called.
NOTE: fun_4(int) in derived class is different from virtual function fun_4() in base
class as prototype of both the function is different.
.
Pure Virtual Functions and Abstract Classes in C++
Sometimes implementation of all function cannot be provided in a base class
because we don’t know the implementation. Such a class is called abstract
class. For example, let Shape be a base class. We cannot provide implementation of
function draw() in Shape, but we know every derived class must have
implementation of draw(). Similarly an Animal class doesn’t have implementation of
move() (assuming that all animals move), but all animals must know how to move.
We cannot create objects of abstract classes.
A pure virtual function (or abstract function) in C++ is a virtual function for which we
don’t have implementation, we only declare it. A pure virtual function is declared by
assigning 0 in declaration. See the following example.
// An abstract class
class Test
public:
/* Other members */
};
A complete example:
A pure virtual function is implemented by classes which are derived from a Abstract
class. Following is a simple example to demonstrate the same.
#include<iostream>
class Base
int x;
public:
};
// This class inherits from Base and implements fun()
int y;
public:
};
int main(void)
Derived d;
d.fun();
return 0;
Output:
fun() called
Some Interesting Facts:
1) A class is abstract if it has at least one pure virtual function.
In the following example, Test is an abstract class because it has a pure virtual
function show().
#include<iostream>
class Test
int x;
public:
};
int main(void)
Test t;
return 0;
Output:
Compiler Error: cannot declare variable 't' to be of abstract
type 'Test' because the following virtual functions are pure
within 'Test': note: virtual void Test::show()
2) We can have pointers and references of abstract class type.
For example the following program works fine.
#include<iostream>
class Base
public:
};
public:
};
int main(void)
bp->show();
return 0;
Output:
In Derived
3) If we do not override the pure virtual function in derived class, then derived class
also becomes abstract class.
The following example demonstrates the same.
#include<iostream>
class Base
public:
};
int main(void)
Derived d;
return 0;
#include<iostream>
class Base
protected:
int x;
public:
};
int y;
public:
void fun() { cout << "x = " << x << ", y = " << y; }
};
int main(void)
d.fun();
return 0;
Output:
x = 4, y = 5