2010-06-18 18 views
26

Sto tentando di stampare l'indirizzo di una funzione membro virtuale. Se so che classe implementa la funzione posso scrivere:Indirizzo di stampa della funzione membro virtuale

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

Ma voglio fare qualcosa di simile:

A *b = new B(); 

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

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

risposta

1

Non ha molto senso per me. Se si dispone di una funzione normale:

void f(int n) { 
} 

allora si può prendere il suo indirizzo:

f 

ma non si può prendere l'indirizzo di una funzione chiamata, che è quello che ti sembra di voler fare .

+0

@GMan Questo è quello che pensavo di aver detto. Ad ogni modo, non penso sia possibile. –

1

Da quello che posso dire nello standard, l'unica volta che si ottiene il binding dinamico è durante una chiamata virtuale chiamata. E una volta che hai chiamato una funzione, stai eseguendo le istruzioni all'interno della funzione (ad esempio, non puoi "interrompere a metà strada nella chiamata e ottenere l'indirizzo.)

Penso che sia impossibile.

+0

Suppongo che sia impossibile da trasportare, ma conoscendo l'implementazione dovrebbe essere possibile ispezionare la tabella virtuale di un oggetto in fase di runtime. –

6

I puntatori alle funzioni membro non sono sempre semplici indirizzi di memoria. Vedere la tabella in this article che mostra le dimensioni dei puntatori funzione membro su diversi compilatori - 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. È possibile 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.

+4

Eppure il problema rimane: come si identifica la funzione che viene chiamata attraverso una chiamata 'virtuale' :)? –

+1

Non era parte della domanda, vero? Ma risponderei 'chiamandolo' :) – AshleysBrain

11

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 prevede un'estensione che ci permette di recuperare l'indirizzo di una funzione virtuale:

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

... assumendo la funzione membro ha 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.

Problemi correlati