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


For example, I have two "intefaces" and a class type:

class IPlugin { public: virtual void Load(void) = 0; virtual void Free(void) = 0; }; class IFoo { public: virtual void Foo(void) = 0; }; class Tester: public IPlugin, public IFoo { public: Tester() {}; ~Tester() {}; virtual void Load() { // Some code here } virtual void Free() { // Some code here } virtual void Foo(void) { // Some code here } }; 

What vtab structure actually has, for example, the type Tester ? And how the dynamic_cast operator will work (I mean, how the dynamic_cast operator scans vtab for the actual conversion of the reference type) in the expression:

 Tester* t = new Tester(); IPlugin* plg = dynamic_cast<IPlugin*>(t); IFoo* f = dynamic_cast<IFoo*>(plg); 

Thanks in advance!

+4
source share
4 answers

Virtual tables in C ++ are implementation details. One possible implementation is shown in the diagram below.

Virtual table diagram

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

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

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

It is clear that the caller using the IFoo pointer IFoo not know any information about the part related to the IFoo part of the class. The same can be said for the caller using the IPlugin pointer. This pointer points to the start of the instance data that the Tester pointer points to, but only the caller using the Tester pointer knows the entire layout of the instance data.

Using dynamic_cast requires RTTI (runtime type information), which is not shown in the diagram. Vtbl will contain additional type information that the IFoo pointer IFoo to the Tester instance, so that the code at runtime detects the actual type of the object that the pointer points to and uses it to lower the pointer.

+17
source

What vtab structure actually has, for example, the type Tester?

The virtual dispatch mechanism is determined by the implementation. vtable and vptr are not required by the C ++ standard and that knowledge is not required for C ++ programmers because you cannot access a virtual table (even if your compiler implements this); its generated by the compiler and added to your code, similar to how it does a lot of things for your code before it converts it to machine code.


 Tester* t = new Tester(); IPlugin* plg = dynamic_cast<IPlugin*>(t); IFoo* f = dynamic_cast<IFoo*>(plg); 

Here dynamic_cast not required in the second line. Enough:

 Tester* t = new Tester(); IPlugin* plg = t; //upcast - dynamic_cast not needed IFoo* f=dynamic_cast<IFoo*>(plg); //horizontal-cast - dynamic_cast needed 

dynamic_cast not required in upcast; it is necessary only in a suppressed and horizontal version.

 Tester* tester1 = dynamic_cast<Tester*>(plg); //downcast - dynamic_cast needed Tester* tester2 = dynamic_cast<Tester*>(f); //downcast - dynamic_cast needed 
+5
source

In ISO / IEC 14882 Second Edition 2003-10-15, there are no such terms as vptr, a virtual table, so it is completely related to compiler implementers.

Information about impl. in Microsoft Visual C ++: http://www.openrce.org/articles/files/jangrayhood.pdf

An article about impl. virtual tables in g ++: http://phpcompiler.org/articles/virtualinheritance.html

+4
source

The virtual mechanism (virtual pointer and virtual table) is not defined by the C ++ standard. The compiler cannot implement the mechanism in its own way. This is a compiler implementation detail. Given that the details of how the compiler implements the virtual mechanism are abstracted from the user. It is important to keep in mind only those that are expected from the virtual engine.

In your case:

 Tester* t = new Tester(); IPlugin* plg = dynamic_cast<IPlugin*>(t); IFoo* f = dynamic_cast<IFoo*>(plg); 

plg and f will both point to a valid object of their respective types, because t comes from both of them.

Of course, this does not answer the question you asked, but simply wants to clear the details of the virtual mechanism, which is a detail of the implementation of compilers.

+3
source

Source: https://habr.com/ru/post/1271243/


All Articles