Il puntatore del tavolo virtuale in molte implementazioni C++ è il primo sizeof(void (**)())
byte dell'oggetto. Quando si dereferenzia quel puntatore si otterrà l'indirizzo iniziale della tabella virtuale reale. Questo è il significato del codice funzionante.
Il programma cdecl
potrebbe essere di po 'di aiuto qui:
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
Il primo codice getta il puntatore per l'oggetto come un puntatore correttamente derefereancable (puntatore a puntatore a puntatore a funzione, void (***)()
) e quindi dereferenziare per acquisire l'indirizzo iniziale della tabella virtuale, che è di tipo void (**)()
(puntatore a puntatore alla funzione), che punta all'inizio della tabella virtuale che è di tipo void (*[])()
(matrice di poin ter to function).
Il secondo getta il puntatore all'oggetto su un puntatore a un puntatore a una funzione che restituisce il vuoto; l'indirizzo memorizzato nella variabile vt è solo l'indirizzo del tuo oggetto.
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;
Così facendo
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
fonte
2013-08-15 03:57:20
Grazie per avermi spiegato questo. Molto illuminante! – Alex