Mechanism of Vptr and Vtable in C++

Mechanism of Vptr and Vtable in C++

Just went through this link virtual table and _vptr

It says that the workflow will be like ..

  1. base_ptr->base_vptr----> to check the access of virtual function in base class.

  2. base_ptr->derived_vptr->virtual_function()---> to call/invoke the virtual function.

Hence the derived class virtual function is called.. Hope you find it helpful.

How vptr and vtable works in the bellow virtual related code?

But i am not understanding that how would i describe the statement p->base::display(); in terms of vptr and vtable .how the compiler will bind the display function of base class version

Vptr is not involved in that call in any way. Vptr is only used in virtual dispatch.

The use of explicit scope resolution in that call means that you are using static dispatch. You are saying, call the function base::display regardless of the dynamic type of the object argument.


Virtual dispatch is a form of runtime polymorphism and a key feature of object oriented programming. When a function call is dispatched virtually, the call is dispatched to the most derived override of the function in the inheritance hierarchy, which depends on the dynamic type of the object.

A function call dispatched statically in contrast is dispatched using compile time name resolution, which is not affected by the dynamic type of the object. This is the default type of dispatch that is used in C++. It is also typically the only type of dispatch in imperative, non-object oriented languages such as C.

Virtual dispatch can only be used with virtual functions. Virtual dispatch is typically implemented using a virtual function table (vtable) and virtual function pointer (vptr).

C++ Virtual Pointer and its mechanism

I really think that related answer has all you need to know, but there might be a bit missing.

The vtable is implementation defined, so anything that works is OK according to the standards.

One way to do it is to have the actual vtable be const static, and in each constructor the single pointer is updated to point to each new class vtable. This has double indirection penalty, but one benefit is it is impossible for malware to overwrite the function pointer.

Another method is to have a table, aka array, of pointers. Virtual pointer table: vtable. In this method each set of pointers is set during each constructor. Or at least it appears that way: optimizers can do strange things.

Things can get extremely complicated with multiple inheritance, multiple virtual inheritance, etc. There could even be nested vtables: tables pointing to other tables!

Then of course we get whole program optimization. LTO on Unixes. LTCG in MSVC, etc. The optimizer can go through the program and if it can determine that the virtual call can only go to one target function, then it replaces the call with a non-virtual direct call. Then reruns the inlining pass. Profile directed optimization can even take a variable virtual function and determine it is calling class A 80% of the time. Then it might always call A, with an out-of-line check to see if it was actually B or something else.

But in the simple case you laid out, class Base has a vtable with one function pointer to foo. When the Base() constructor runs it is set to Base::foo. After Derived() runs it is set to Derived::foo()

Without complex virtual inheritance or multiple inheritance, the base (Base in your case) class is always at the front of the structure. So a pointer to Base always points to the front. Where the vtable is. Pointers to Derived also point to the front. Both classes use the same vtable and call whichever function is set there.

How are virtual functions and vtable implemented?

How are virtual functions implemented at a deep level?

From "Virtual Functions in C++":

Whenever a program has a virtual function declared, a v - table is constructed for the class. The v-table consists of addresses to the virtual functions for classes that contain one or more virtual functions. The object of the class containing the virtual function contains a virtual pointer that points to the base address of the virtual table in memory. Whenever there is a virtual function call, the v-table is used to resolve to the function address. An object of the class that contains one or more virtual functions contains a virtual pointer called the vptr at the very beginning of the object in the memory. Hence the size of the object in this case increases by the size of the pointer. This vptr contains the base address of the virtual table in memory. Note that virtual tables are class specific, i.e., there is only one virtual table for a class irrespective of the number of virtual functions it contains. This virtual table in turn contains the base addresses of one or more virtual functions of the class. At the time when a virtual function is called on an object, the vptr of that object provides the base address of the virtual table for that class in memory. This table is used to resolve the function call as it contains the addresses of all the virtual functions of that class. This is how dynamic binding is resolved during a virtual function call.

Can the vtable be modified or even directly accessed at runtime?

Universally, I believe the answer is "no". You could do some memory mangling to find the vtable but you still wouldn't know what the function signature looks like to call it. Anything that you would want to achieve with this ability (that the language supports) should be possible without access to the vtable directly or modifying it at runtime. Also note, the C++ language spec does not specify that vtables are required - however that is how most compilers implement virtual functions.

Does the vtable exist for all objects, or only those that have at least one virtual function?

I believe the answer here is "it depends on the implementation" since the spec doesn't require vtables in the first place. However, in practice, I believe all modern compilers only create a vtable if a class has at least 1 virtual function. There is a space overhead associated with the vtable and a time overhead associated with calling a virtual function vs a non-virtual function.

Do abstract classes simply have a NULL for the function pointer of at least one entry?

The answer is it is unspecified by the language spec so it depends on the implementation. Calling the pure virtual function results in undefined behavior if it is not defined (which it usually isn't) (ISO/IEC 14882:2003 10.4-2). In practice it does allocate a slot in the vtable for the function but does not assign an address to it. This leaves the vtable incomplete which requires the derived classes to implement the function and complete the vtable. Some implementations do simply place a NULL pointer in the vtable entry; other implementations place a pointer to a dummy method that does something similar to an assertion.

Note that an abstract class can define an implementation for a pure virtual function, but that function can only be called with a qualified-id syntax (ie., fully specifying the class in the method name, similar to calling a base class method from a derived class). This is done to provide an easy to use default implementation, while still requiring that a derived class provide an override.

Does having a single virtual function slow down the whole class or only the call to the function that is virtual?

This is getting to the edge of my knowledge, so someone please help me out here if I'm wrong!

I believe that only the functions that are virtual in the class experience the time performance hit related to calling a virtual function vs. a non-virtual function. The space overhead for the class is there either way. Note that if there is a vtable, there is only 1 per class, not one per object.

Does the speed get affected if the virtual function is actually overridden or not, or does this have no effect so long as it is virtual?

I don't believe the execution time of a virtual function that is overridden decreases compared to calling the base virtual function. However, there is an additional space overhead for the class associated with defining another vtable for the derived class vs the base class.

Additional Resources:

http://www.codersource.net/published/view/325/virtual_functions_in.aspx (via way back machine)

http://en.wikipedia.org/wiki/Virtual_table

http://www.codesourcery.com/public/cxx-abi/abi.html#vtable

Why vptr is not static?

The runtime class of the object is a property of the object itself. In effect, vptr represents the runtime class, and therefore can't be static. What it points to, however, can be shared by all instances of the same runtime class.

When exactly does the virtual table pointer (in C++) gets set for an object?

This is strictly Implementation dependent.

For Most compilers,

The compiler initializes this->__vptr within each constructor's Member Initializer list.

The idea is to cause each object's v-pointer to point at its class's v-table, and the compiler generates the hidden code for this and adds it to the constructor code. Something like:

Base::Base(...arbitrary params...)
: __vptr(&Base::__vtable[0]) ← supplied by the compiler, hidden from the programmer
{

}

This C++ FAQ explains a gist of what exactly happens.

is vptr name mangled in c++?

The C++ standard doesn't even acknowledge the existence of a vptr in polymorphic classes because it's an implementation detail and therefore it isn't even a requirement that compilers implement virtual functions in this way. So no, vptr is not a reserved keyword (which is what I think you're trying to ask).

What is the structure of virtual tables in C++?

Virtual tables in C++ is an implementation detail. One possible implementation is shown on the diagram below.

Virtual table diagram

Two instances of the class (A and B) exists. Each instance has two vtbl pointers and the vtbl contains pointers to actual code.

In your example there is no instance data, but I have for illustrative purposes assumed that each class contains some instance data.

When a pointer to Tester is cast to a pointer to IFoo the pointer is adjusted as shown on the diagram. Instead of pointing to the start of the instance data it points to the IFoo part of the instance data.

The neat thing is that a caller using an IFoo pointer doesn't have any knowledge about the data surrounding the IFoo part of the class. The same can be said of for a caller using an IPlugin pointer. This pointer happens to point to the start of the instance data also pointed to by a Tester pointer but only a caller using a Tester pointer knows the entire layout of the instance data.

Using dynamic_cast requires RTTI (Run-Time Type Information) which is not on the diagram. The vtbl will contain additional type information that given a say IFoo pointer to an instance of Tester allows the code at run-time to discover the actual type of object pointed by the pointer and use that to downcast the pointer.



Related Topics



Leave a reply



Submit