Virtual Functions Explored - C++ C# examples
A complete understanding of everything is very important in the programming world. I am taking this post to just give some explanations I know and the understanding I have with the Virtual Functions. This is an explanation given by one of the trainer who taught me C#. I'm not sure whether he has a blog or a personal website, if yes, I will definitely link him in my post.
Virtual functions are normal member functions of a class, which can be over-ridden in the derived classes. The whole functionality can be replaced in the over-riding function. In C#, the virtual functions will be declared with a keyword 'virtual' and the over-riding functions will be declared with 'override' key word.
Example in C#:
using System;
namespace ConsoleApplication1
{
class BaseClass
{
public BaseClass()
{
// TODO
}
virtual public void MyFunction1()
{
Console.WriteLine("MyFunction in Base class");
}
virtual public void MyFunction2()
{
Console.WriteLine("MyFunction in Base class");
}
}
class DerivedClass : BaseClass
{
public DerivedClass()
{
// TODO
}
override public void MyFunction1()
{
Console.WriteLine("MyFunction in Derived class");
}
}
class Program
{
static void Main(string[] args)
{
DerivedClass b = new DerivedClass();
b.MyFunction();
}
}
}
How the call to the derived class virtual function is being made? Let me present a C++ equivalent of the above code:
class BaseClass
{
public:
BaseClass()
{
}
virtual public void MyFunction1()
{
cout<<"MyFunction1 in Base class"<<endl;
}
virtual public void MyFunction2()
{
cout<<"MyFunction2 in Base class"<<endl;
}
};
class DerivedClass
{
public:
DerivedClass ()
{
}
public void MyFunction()
{
cout<<"MyFunction in Base class"<<endl;
}
};
void main()
{
DerivedClass *obj;
obj->MyFunction();
}
I am going to explain the virtual functions with the C++ example and will give some more additional code which will explain the call semantics of the virtual functions. Whenever, there is a virtual function in the class, a v-table is constructed in the memory. The v-table has a list of addresses to the virtual functions of the class and pointers to the functions from each of the objects of the derived class. When a virtual function call is made, the v-table is used to get the addresses of the function and the function is called.
Let me also explain what are the steps that executed in a constructor. Before it executes the 1st line of code in the constructor body, the following steps are performed:
1. Base class constructer is called
2. Call the contained object constructors
3. Set the VPtr
The step we are interested is the 3rd step - setting the VPtr. Every object has a VPtr and is stored in the 1st memory location of the object memory. VPtr will have the address of the Virtual Table which has the function addresses of all the virtual functions available. Using the Vptr we can easily access the VirtualTable of the class and make function calls as normally done with the help of function pointers. So, as you all guessed by now, the base class constructor will be called and the VPtr of the base class will be set. But, when the call returns to the derived class constructor, the derived class VPtr will be set to its own VTable address.
How to get the VPtr of the class?
long *vptr = (long *) &obj;
// gets the vptr of the class which is stored in the 1st memory location of each object of the class
We got the VPtr, how we need to get the address of the VTable which is also a pointer.
long *vtable = (long *)*vptr;
// get the vtable address
VTable can be considered as an array of function pointers. The addresses of virtual functions declared in the class will be stored in the order they are declared. The 0th location will have the 1st virtual function's address, 1st location have the 2nd virtual function address, so on and so forth. Now we have the address of the VTable in the pointer vtable. Lets declare a function pointer.
typedef void (__stdcall *FunctionPtr)();
FunctionPtr fp = (FunctionPtr)vtable[0];
// pointing to MyFunction1 which is in the 0th location of the v-table
We have also declared fp which is a function pointer holding a function that returns void, accepting no arguments. Let's now call the function:
fp();
fp = (FunctionPtr)vtable[1]; // pointing to 1st location which has MyFunction2
fp();
Now, lets talk about setting the VPtr (3rd step in a constructor - before any user written code is executed). It does set the Virtual Table address. It is just another step which is performed when ever a constructor is called. Now, lets review the below lines of code:
DerivedClass *ptr = new DerivedClass();
ptr->MyFunction1(); // calls DerivedClass MyFunction1
ptr->BaseClass::BaseClass(); // BaseClass constructor is called - so VPtr altered to point to BaseClass's VTable
ptr->MyFunction1(); // calls BaseClass MyFunction1
From the comments you would have understood what is really happening. Fortunately, C# doesn't provide a way to call a base class constructor. However, you can use new operator to create a new copy of the BaseClass in this scenario to achieve the same result.
Are you a person who wish to combine many steps into one (hates to waste time in typing few more lines of code or love to minimize memory utilization by reducing the no. of variables declared or confuse someone who may try to understand your code)? If you are, following is another method of calling the first virtual function of that class:
((void(*)())*(long *)*(long *)&obj)();
Cool deal ha? Happy learning!
Comments
Anonymous
June 15, 2007
Great article!Anonymous
August 24, 2007
very good article, i was long waiting to study about vtable and vptr. article was very good, ofco'z its a tugh concept. i must read it more than once to understand clear.. good job.Anonymous
January 25, 2010
Good explanation for a beginner.Anonymous
August 17, 2010
Gr8 Stuff buddy NICE DEMONSTRATION!!!!THNXAnonymous
November 29, 2010
Clearly understandable.. done a great job..very niceAnonymous
December 06, 2010
Excellent information about of virtual functions which i have not known.Thanks for uploading such precious asset....Anonymous
June 05, 2011
Now i can understand virtual function very well it is a good example thanx............:-)Anonymous
June 05, 2011
Now i Can understand virtual function very well goo example thanx