void (**vt)() = *(void (***)())ptr; a helper variable for virtual table in c++

c++

Solution

The virtual table pointer in many C++ implementations is the first `sizeof(void (**)())` bytes of the object. When you dereference that pointer you will get the starting address of the real virtual table. That is the meaning of the working code.

The `cdecl` program might be of bit of a help here:

cdecl> explain void (***foo)()
declare foo as pointer to pointer to pointer to function returning void
cdecl> explain void (**foo)()
declare foo as pointer to pointer to function returning void

The first code casts the pointer to your object as a properly derefereancable pointer (pointer to pointer to pointer to function, `void (***)()`), and then dereferences it to acquire the starting address to the virtual table, which is of a type `void (**)()` (pointer to pointer to function), which points to the beginning of the virtual table that is of type `void (*[])()` (array of pointer to function).

The second one just casts your pointer to object to a pointer to a pointer to a function returning void; the address stored in the variable vt is just the address of your object.

class Object {
public:
    virtual void foo() {};
};

Object x;

// is approximately equivalent to 

struct Object {
    void (**_vtable)();
};

void _Object_foo(Object this) {
}

// this does not really compile, however,
// because a pointer mismatch
void (*_vtable_for_Object[])() = {
    _Object_foo
};

Object y;
y._vtable = _vtable_for_Object;

Thus by having

Object *ptr = new Object();
// x now points to a block of memory,
// whose first bytes are void (**_vtable)()

// then
void (**vt)() = *(void (***)())ptr;

// is equivalent in our analogy to
void (**vt)() = ptr->_vtable;

// except that the C++ does not allow you to
// access the virtual table directly without
// the trickery of the former

Problem

I found this technique in the following link: http://www.codeproject.com/Tips/90875/Displaying-vtable-when-debugging and there, he uses one helper variable ``` void (**vt)() = *(void (***)())ptr; ``` to help display the virtual function table. But if I change it to ``` void (**vt)() = (void (**)())ptr; ``` it does not work as the previous one. Could someone help me to explain what magic plays here, please?

Original source