Two questions related to virtual functions

前端 未结 4 1179
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-20 02:28

I was reading this articles , was at this heading Inheritance of Base-class vPtrs , but couldn\'t understand what did he mean in this para :

"However, due to mul

4条回答
  •  庸人自扰
    2020-12-20 02:44

    With regards to your first question, I don't really follow what the quoted passage is getting at; it actually sounds like the author doesn't really understand how vtables work (or hasn't thought about it in detail). It's important to realize that when we speak of “merging” the base and the derived classes' vtables, we are talking about making the base class vtable a prefix of the derived class table; the base class vtable must start at the start of the derived class vtable for this to work; the offset of the vptr in both the base and the derived must be identical (almost always 0, in practice), and the base class must be placed at the very beginning of the derived. And of course, it's only possible to fulfil those conditions for one base class. (Most compilers will use the first non-virtual base appearing in a left to right scan of the code.)

    With regards to the expression, it's completely undefined behavior, and will not work with some compilers. Or may or may not work, depending on the level of optimization. And the void* in it is being used as a placeholder for any number of pointer types (including, probably, pointer to function types). If we take the inner-most part, we're saying that &a is a pointer to (1 or more) void*. This pointer is then dereferenced ((X)[0] is the same as *(X), so (((void**)(&a))[0]) is the same as *(void**)(&a). (The [0] notation suggests that there might be more values behind this one; i.e. that [1], etc. might also be valid. That's not the case here.) This results in a void*, which is then cast to a void** and once again dereferenced, this time really using an index (since it is hopefully into an array); the result of this dereferencing is converted to a foo (a pointer to a function), which is then dereferenced and the function is called without any arguments.

    None of this will actually work. It makes a number of suppositions which are not always, or in some cases even generally, true:

    • The offset of the vptr in an object is 0. (This one is generally true.)
    • The vptr itself has the same size as a void*. (This is almost always true, and required by Posix.)
    • The vtable itself is an array of pointers to functions, and that pointers to functions have the same size as a void*. And while it's true that pointers to functions do often have the same size as void* (again, Posix requires it, and it's also true under Windows), it's hard to imagine an implementation which would work if the vtable were just an array of pointers to functions.
    • That the function called doesn't actually use the this pointer: this is only true in exceptional cases.

    He apparently is using VC++ (based on the __thiscall, which is a Microsoft'ism), and I've only analysed the layout of Sun CC, which is definitely different. (And Sun CC and g++ are also very different—for that matter, Sun CC 3.1, Sun CC 4.0 and Sun CC 5.0 are all different.)

    Unless you're actually writing a compiler, I'd ignore all of this. And I'd certainly ignore the expression you quote.

提交回复
热议问题