Our social:

Tuesday, October 4, 2016

C++ Ploymorphism and Virtual Function-C++ Tutorial

The word Polymorphism means having many forms

Using polymorphism we can assign different meaning or usage to something in different contexts - specifically, allowing an entity like variable, function, or object to have more than one form. There are different kinds of polymorphism.
In Object Orient Programming, polymorphism represents possibility to have multiple implementations of the same functions. You can see a simple example of polymorphism in "C++ Overloading". A function with the same name can have different behavior according to the context of its call. The most interesting concepts of polymorphism are related to Inheritance. A pointer of base class can be used as pointer of derived class. Look at the following hierarchy of classes:

class baseClass
{
public:
	baseClass(int val) :someValue(val)
	{

	}
	void info()
	{
		cout << "Info member function of base class" << endl;
	}
protected:
	int someValue;
};

class derivedClass1 : public baseClass
{
public:
	derivedClass1(int val) :baseClass(val)
	{

	}
	void info()
	{
		cout << "Info member function of derived class 1" << endl;
	}
};

class derivedClass2 : public baseClass
{
public:
	derivedClass2(int val) :baseClass(val)
	{

	}
	void info()
	{
		cout << "Info member function of derived class 2" << endl;
	}
};

We can use pointer of a base class as a pointer of the derived class:
	
derivedClass1 child1(1);
derivedClass2 child2(2);

//pointers to base class
baseClass* basePtr1;
baseClass* basePtr2;

//make pointers to base class point to objects of derived classes
basePtr1 = &child1;
basePtr2 = &child2;
It seems to be very easy to use pointers of the base class as pointers of the derived class. But the problem appears when
  • We want to call a member function of a derived class that does not exist in the base class or
  • The function which we want to call is overridden in the derived class
Base class and two derived classes have the same function info(). Try to call this function by using pointer to base class as below:

//calling info function
basePtr1->info();
basePtr2->info();
In this case, info() member function of a derived classes will not be called. Instead the info() function of base class will be called. Below is the output of above calls:
Info member function of base class
Info member function of base class

Static Cast

We can use static cast to work with pointer of the base class as pointer of the derived class:

//use static cast and call info from derived class 1
static_cast<derivedClass1*> (basePtr1)->info();
In this case, member function info() from derivedClass1 will be called:
Info member function of derived class 1

Virtual Functions

Virtual functions are functions those are expected to be overridden in the derived class. By using Virtual function we can call functions of a derived class using pointer of the base class.
Declaration of a virtual function is done by using virtual keyword before declaration of a function as shown below:

virtual function-declaration;
Try to declare function info() of the baseClass as virtual function:

virtual void info()
{
	cout << "Info member function of base class" << endl;
}
Now, try to call info function by using pointer of the base class:

derivedClass1 child1(1);
derivedClass2 child2(2);

//pointers to base class
baseClass* basePtr1;
baseClass* basePtr2;

//make pointers to base class point to objects of derived classes
basePtr1 = &child1;
basePtr2 = &child2;

//call info
basePtr1->info();
basePtr2->info();
The appropriate member function of each derived class will be called without any casts then output will be:
Info member function of derived class 1
Info member function of derived class 2
Try to remove info() member function from derivedClass1 and compile this code again then output will be:
Info member function of base class
Info member function of derived class 2
As you can see, compiler first looks for info() member function in the appropriate derived class. If it cannot find member function in the derived class, it will call member function of the base class.

Late binding (Runtime Polymorphism)

Late binding is also known as Dynamic Binding or Runtime Binding.
Sometimes compiler can’t know which function will be called till program is executed (runtime). This is known as late binding.
Binding is the process which is used by the compiler to convert identifiers (such as variable and function names) into machine language addresses.
It is a mechanism in which the method called by an object gets associated by name in runtime. Late binding happens when virtual keyword is used in member function declaration.

Mechanism of Late Binding

C++ implementation of virtual functions uses a special form of late binding known as virtual table(VTable). When a class declares a virtual member function, most of the compilers add a hidden member variable that represents a pointer to Virtual Method Table (VMT or VTable). We will call this pointer as vptr. This table represents an array of pointers to virtual functions. At compile-time, there is no information about which function will be called. At runtime, pointers from Virtual Method Table will point to right functions.
Look on the following example:

class A
{
public:
	virtual void function1() {};
	virtual void function2() {};
};

class B : public A
{
public:
	virtual void function1() {};
};

class C : public A
{
public:
	virtual void function2() {};
};
When an object of any class is created, it has its own pointer to VMT:
VTable
When a function is called from an object, it will look in the corresponding VMT of that object.

Virtual Destructor

Destructor is called when an object is destroyed. C++ provides a default destructor for all the classes. However, sometimes there is a need to create your own destructor. It can be done in the case you need to deallocate memory, free a resource etc.
When you have a hierarchy of classes, it is strongly recommended to use virtual destructors. Declaration of Virtual Destructor looks in the following way:

virtual ~ClassName()

Why to use virtual destructors?

Upcasting without Virtual Destructor

Look on the following example:

class A
{
public:
	~A()
	{
		cout << "Base class destructor" << endl;
	}
};

class B : public A
{
public:
	~B()
	{
		cout << "B class destructor" << endl;
	}
};

int main()
{
	A* a = new B;
	delete a;
}
As you can see, pointer "a" points to an object of type B. When "a" is deleted, only the destructor of base class will be called. This means, that the object of a derived class will not be destroyed properly.
This problem is easily resolved with Virtual Destructor.

Upcasting with Virtual Destructor

Try to modify previous example by changing the destructor of base class to virtual:

class A
{
public:
	virtual ~A()
	{
		cout << "Base class destructor" << endl;
	}
};

class B : public A
{
public:
	~B()
	{
		cout << "B class destructor" << endl;
	}
};

int main()
{
	A* a = new B;
	delete a;
}
When base class destructor is virtual, the derived class destructor is called first and after this, base class destructor is called:
B class destructor
Base class destructor

Abstract Class and Pure Virtual Function

An Abstract class is a class that has at least one pure virtual function. A pure virtual function is a function without definition. To declare pure virtual function use the following syntax:

virtual return-type function-name(parameter-list) = 0;
For example, we can modify above baseClass to make it abstract class:

class baseClass
{
public:
	baseClass(int val) :someValue(val)
	{

	}
	//pure virtual function
	virtual void info() = 0;
protected:
	int someValue;
};
Now, info() is a pure virtual function. In this case when you use a pure virtual function then you mustoverride it in the derived classes. You cannot create an object of the abstract class, but you can still use pointers of a base class to point an objects of the derived class.

Pure Virtual Destructor

As we know that, pure virtual functions are functions those are not defined (implemented). If a class has at least one pure virtual function, it becomes abstract.
C++ provides possibility to create pure virtual destructors. Pure virtual destructor also makes a class an abstract class, but there is a difference between pure virtual function and pure virtual destructor. Pure virtual destructor must be implemented:

class A
{
public:
	virtual ~A() = 0;
};

A::~A()
{
	cout << "Base class destrctor" << endl;
}

Pure Virtual Function with Function Body

Yes we can have a pure virtual function with a body as shown below
class Base
{
   	int x;
public:
    	virtual void fun() = 0
	{
		cout<<"Base Class fun() is Called";
	}
    	int getX() 
	{ 
		return x; 
	}
};
 
class Derived: public Base
{
    	int y;
public:
    	void fun() 
	{ 
		cout << "Derived Class fun() called"; 
	}
};
 
int main(void)
{
    	Derived d;
    	d.fun();
	//Calling Base Class Pure Virtual Function fun()
	Base::fun();
    	return 0;
}
 To call Pure Virtual Function we should use the class name Class_Name::Function_Name

Use of Pure Virtual Function with a function body

Sometimes if you want to call base class function which is having the common functionality to be called in derived classes then instead of rewriting same logic multiple times we can write common logic in pure virtual function's body.

               

   C++ Upcasting and Downcasting

0 comments:

Post a Comment

Hello Every One thanks For Visit My site You Can Suggest any Idea About site And Related Education Information Provide me Its Best Content For you am Include in this Site And feel free contact And email now I hope This site very help full you