Virtual Function
class myClassBase
{
public:
int baseMember;
virtual int getVal(int x) { return baseMember + x; }
};
The equivalent C code:
struct myClassBase
{
void *vtable;
int baseMember;
};
int myClassBase_getVal(struct myClassBase *this, int x)
{
return this->baseMember + x;
}
struct
{
long abiVerInfo;
char *typeName;
}
myClassBase_typeInfo =
{
0, // ABI related stuff.
"myClassBase"
};
struct
{
void *typeInfo;
int (*fun1)(struct myClassBase *, int);
}
myClassBase_vtable =
{
&myClassBase_typeInfo,
myClassBase_getVal
};
void myClassBase_ctor(struct myClassBase *this)
{
this->vtable = (void*)&myClassBase_vtable + sizeof(void*);
}
If we create an object of myClassBase, then a diagram describing the above will be as-

Points to understand:
- There is a vtable and typeinfo generated for each class that has virtual function (the class defines itself or inherits from base)
- The typeifo contains the type name and other info to uniquely identify the class name.
- vtable contains pointers to typeinfo and function pointers of all virtual functions defined by the class.
- the object contains the pointer to the vtable. The pointer to vtable in the object points to the first entry in the function pointer table.
- There is a constructor generated even if we did not write in the C++ code. This constructor sets the vtable pointer of the object to the vatable that is generated for the class.
Format of vtable
The vtable contains more than the function pointers. This is like -
Info X Info Y ..... Vfun1 Vfun2 ....
In general, the vtable can contain one or more info with function pointer table. One of them is typeifo pointer. The object points into the vtable at the offset from where the function pointer starts. This model simplifies the access of virtual functions from the object. If we need to access to other info that is contained in vtable, then we go to the memory location pointed by vtable of object then move the pointer backward.
Format of typeInfo:
Like vtable, the typeinfo contains more fields than a pointer to type name string. These fields are used while casting of objects and runtime type identification. But we will ignore those fields here for simplicity. The type name used in C code and in the diagram is not mangled, but in the actual generated code, this is mangled. Again this is done for readability.
If we call the virtual function, the generated code will be -
struct myClassBase *mycs = operator_new(sizeof(struct myClassBase)); myClassBase_ctor(mycs); typedef int (*memFunPtr)(struct myClassBase *, int); memFunPtr fptr= mycs->vtable; fptr(mycs, 10);
Here, unlike the non-virtual function, the method binding happens at run time. The actual method that is invoked, is decided at runtime by looking into the vtable. In the case of non-virtual function, the compiler generates the code to invoke the method directly without looking into any function pointer table. The compiler has info of which method to call at compile time and generates the code for the invocation of that particular function.
The vtable defines the function pointer in the sequence defined in the C++ code. Now you can guess why the C++ code has to be recompiled if the library code changes the order of declaration of virtual functions.