Dynamic Binding Through Virtual Functions in C++

This is an article on Dynamic Binding Through Virtual Functions in C++ in C++.

Rated 5.00 By 1 users

A virtual function is used where we want to allow the derived class to replace the implementation of the same function in base class. The compiler always calls the derived class function when called with object of the derived class or an object of base class holding the address of the derived class object. The derived class can fully replace the definition of the base class virtual function or could partially replace by calling the base class function in the implementation of the derived class function.

A virtual function is declared by using the 'virtual' prefix to the declaration of that function. A call to virtual function is resolved at the run-time by analyzing the actual type of object that is calling the function. This is known as dynamic binding.if the object has one or more virtual functions, the compiler puts a hidden pointer in the object called a "virtual-pointer" or "v-pointer." This v-pointer points to a global table called the "virtual-table" or "v-table."

Compiler creates a virtual table for a class that has at-least one virtual function. For example, if class Vehicle has virtual functions for engine() and body(), there would be exactly one v-table associated with class Vehicle, even if there were a thousand Vehicle objects, and the v-pointer of each of those Vehicle objects would point to the Vehicle v-table. The v-table itself has pointers to each of the virtual functions in the class. For example, the Vehicle v-table would have two pointers: a pointer to Vehicle::engine() and a pointer to Vehicle::body().

Step -3: The compiler initializes this->__vptr within each constructor. The idea is to cause each object's virtual-pointer to point at its class's virtual-table, as if it adds the following instruction in each constructor's init-list:

Code:

Base::Base(/* Some params*/)
: __vptr(&Base::__vtable[0])
...
{
...
}

Now lets look at derived class. Suppose your C++ code defines class Der that inherits from class Base. The compiler repeats steps 1 and 3 (but not 2). In step 1, the compiler creates a hidden virtual-table, keeping the same function-pointers as in Base::__vtable but replacing those pointers that correspond to overrides. For instance, if Der overrides virt0() through virt2() and inherits the others as-is, Der's virtual-table might look something like this (:

In step #3, the compiler adds a similar pointer-assignment at the beginning of each of Der's constructors. The idea is to change each Der object's virtual-pointer so it points at its class's virtual-table. This is not a 2nd virtual-pointer; it's the same virtual-pointer that was defined in the base class.

Finally, let's see how the compiler implements a call to a virtual function:

Code:

// Your original C++ code
void mycode(Base* p)
{
p->virt3();
}

The compiler has no idea whether this is going to call function Base::virt3() or function Der::virt3().It only knows for sure that you are calling virt3() which happens to be the function in slot 3 of the virtual-table.

Hence, in this way the program can bind the function call dynamically to the correct function.

Conclusion

To Conclude, the concept of virtual function act as one of the pillars of the OOPs concept of polymorphism.