Stampa l’indirizzo della funzione membro virtuale

Sto cercando di stampare l’indirizzo di una funzione membro virtuale. Se so quale class implementa la funzione, posso scrivere:

print("address: %p", &A::func); 

Ma voglio fare qualcosa del genere:

 A *b = new B(); printf("address: %p", &b->func); printf("address: %p", &b->A::func); 

Tuttavia questo non viene compilato. È ansible fare qualcosa di simile, magari guardando l’indirizzo in vtable in fase di runtime?

Attualmente non esiste un modo standard per farlo in C ++ sebbene le informazioni debbano essere disponibili da qualche parte. Altrimenti, come potrebbe il programma chiamare la funzione? Tuttavia, GCC fornisce un’estensione che ci consente di recuperare l’indirizzo di una funzione virtuale:

 void (A::*mfp)() = &A::func; printf("address: %p", (void*)(b->*mfp)); 

… assumendo che la funzione membro abbia il prototipo void func() . Questo può essere piuttosto utile quando si desidera memorizzare nella cache l’indirizzo di una funzione virtuale o usarlo nel codice generato. GCC ti avviserà di questo costrutto a meno che tu non specifichi -Wno-pmf-conversions . È improbabile che funzioni con qualsiasi altro compilatore.

I puntatori alle funzioni membro non sono sempre semplici indirizzi di memoria. Vedere la tabella in questo articolo che mostra le dimensioni dei puntatori funzione dei membri su compilatori diversi: alcuni vanno fino a 20 byte.

Come l’articolo delinea un puntatore di funzione membro è in realtà un blob di dati definiti dall’implementazione per aiutare a risolvere una chiamata attraverso il puntatore. È ansible archiviarli e chiamarli correttamente, ma se si desidera stamparli, cosa si stampa? Meglio trattarlo come una sequenza di byte e ottenere la sua lunghezza tramite sizeof .

Non ha molto senso per me. Se hai una funzione normale:

 void f( int n ) { } 

allora puoi prendere il suo indirizzo:

 f 

ma non puoi prendere l’indirizzo di una chiamata di funzione, che è ciò che sembra voler fare.

Da quello che posso dire nello standard, l’unica volta che ottieni l’associazione dynamic è durante una chiamata di funzione virtuale. E una volta che hai chiamato una funzione, stai eseguendo le istruzioni all’interno della funzione (cioè, non puoi “fermarti a metà strada” nella chiamata e ottenere l’indirizzo).

Penso che sia imansible.