Thursday, April 3, 2014

Virtual functions in C++

Problem

How do virtual functions work in C++?

Solution

Virtual functions are defined in a super class. It does not require implementation for the super class. But all the extended class have to implement the function. So, the derived class can override the behavior of the virtual function.

Example
For example, a Shape class can have a virtual draw function. Its derived class, e.g., Circle, has to implement its detailed draw function.


The following snippet shows the usage of the example, it creates an array of Shape class pointers wherein each points to distinct derived class object. At run-time invoking Draw() method results in calling of the method overriden by that derived class and the particular Shape is drawn(rather rendered).
Shape *basep[] = { &line_obj, &tri_obj,
                   &rect_obj, &cir_obj};
for (i = 0; i < NO_PICTURES; i++)
    basep[i] -> Draw ();

Now lets see how it works.
How it works
A virtual function depends on a “vtable” OR “Virtual Table”OR virtual function table OR virtual method table OR even as a dispatch table. .
If any function of a class is declared as virtual, a v-table is constructed which stores addresses of the virtual functions of this class. The compiler also adds a hidden vptr variable in all such classes which points to the vtable of that class. If a virtual function is not overridden in the derived class, the vtable of the derived class stores the address of the function in his parent class.

For example we have shape having 3 virtual function - draw1, draw2, draw 3 and circle implements only draw1 and draw2, this is how the virtual function of shape look like :
V table of circle


The v-table is used to resolve the address of the function, for whenever the virtual function is called.

Dynamic binding in C++ is therefore performed through the vtable mechanism.
Thus, when we assign the derived class object to the base class pointer, the vptr points to the vtable of the derived class. This assignment ensures that the most derived virtual function gets called.
class Shape {
    public:
        int edge_length;
        virtual int circumference () {
            cout << "Circumference of Base Class\n";
            return 0;
        }
};
 
class Triangle: public Shape {
    public:
        int circumference () {
            cout<< "Circumference of Triangle Class\n";
            return 3 * edge_length;
        }
};
 
void main() {
    Shape * x = new Shape();
    x->circumference(); // prints "Circumference of Base Class"
    Shape *y = new Triangle();
    y->circumference(); // prints "Circumference of Triangle Class"
}

In the above example, circumference is a virtual function in shape class, so it becomes virtual in each of the derived classes (triangle, rectangle). C++ non-virtual function calls are resolved at compile time with static binding, while virtual function calls are resolved at run time with dynamic binding.

Pure virtual functions
Notice When you use virtual functions you can declare them as pure virtual(like in class Shape, just place " = 0" after method proto). In this case you won't be able to create instance of object with pure virtual function and it will be called Abstract class.

A abstract function in C++ is defined as:
  
virtual void foo() = 0;


Virtual destructor
Also notice "virtual" before destructor. In case when you are planning work with objects through pointers to their base classes you should declare destructor virtual, so when you call "delete" for base class pointer, all chain of destructors will be called and there won't be memory leaks.

References
http://tianrunhe.wordpress.com/2012/04/12/virtual-functions-in-c/
http://stackoverflow.com/questions/8824359/why-use-virtual-functions
http://stackoverflow.com/questions/9312389/construction-of-the-virtual-table-by-compiler

Reactions:

0 comments:

Post a Comment