开发者

C++ vtable query

开发者 https://www.devze.com 2023-04-03 23:03 出处:网络
I have a query in regard to the explaination provided here开发者_运维技巧 http://www.parashift.com/c++-faq/virtual-functions.html#faq-20.4

I have a query in regard to the explaination provided here开发者_运维技巧 http://www.parashift.com/c++-faq/virtual-functions.html#faq-20.4

In the sample code the function mycode(Base *p), calls virt3 method as p->virt3(). Here how exactly the compiler know that virt3 is found in third slot of vtable? How do it compare and with what ?


When the compiler sees the definition of Base it decides the layout of its vtable according to some algorithm1, which is common to all its derived classes as far as methods inherited from Base are concerned (derived classes may add other virtual methods, but they are put into the vtable after the stuff inherited from Base).

Thus, when the compiler sees p->virt3(), it already knows that for any object that inherits from Base the pointer to the correct virt3 is e.g. in the third slot of the vtable (because that's how it laid out the vtable of Base at the moment of its definition), so it can correctly generate the code for the virtual call.


Long story short (driving inspiration from @David Rodríguez's comment): it knows where it stays because he decided it before.


1. The standard do not mandate any particular algorithm (actually, it doesn't say anything about how the C++ ABI should be implenented), but there are several widespread C++ ABI specifications, notably the COM ABI on Windows and the Itanium ABI on Linux (and in general for gcc). Obviously, given the same class definition, the algorithm must give the same vtable layout every time, otherwise it would be impossible to link together different object modules.


The layout of the vtable is specified by the Itanium C++ ABI, followed by many compilers including GCC. The compiler itself doesn't decide where the function pointers go (though I suppose it does decide to abide by the ABI!).

The order of the virtual function pointers in a virtual table is the order of declaration of the corresponding member functions in the class.

(Example.)

COM — used by Visual Studio — also emits vtable pointers in source order (though I can't find normative documentation to prove that).

Also, because the function name doesn't even exist at runtime (but a function pointer), the layout of the vtable at compile-time doesn't really matter. The function call translation works in just the same way that a normal function call translation works: the compiler is already mapping the function name to an address in its internal machinery. The only difference is that the mapping here is to a location in the vtable, rather than to the start of the actual function code.

This also addresses your concern about interoperability, to some extent.

Do remember, though, that this is all implementation machinery and C++ itself has no knowledge that virtual tables even exist.


The compiler has a well defined algorithm for allocating the entries in the vtable so that the order of the entries will always be the same regardless of which translation unit is being processed. Internal to the compiler is a mapping between the function names and their location in the vtable so the compiler can do the correct transformation between function call and vtable index.

It is important, therefore, that changes to the definition of a class with virtual functions causes all source files that are dependent on the class to be recompiled, otherwise bad things could happen.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号