Non c'è niente di sbagliato nell'usare i puntatori a funzione. Tuttavia, i puntatori a funzioni membro non statiche non sono come i normali puntatori a funzioni: le funzioni membro devono essere chiamate su un oggetto che viene passato come argomento implicito alla funzione. La firma della tua funzione membro sopra è, quindi
void (aClass::*)(int, int)
piuttosto che il tipo che si tenta di utilizzare
void (*)(int, int)
Un approccio potrebbe consistere nel far funzionare il membro, static
nel qual caso non richiede il richiamo di alcun oggetto e puoi usarlo con il tipo void (*)(int, int)
.
Se hai bisogno di accedere a qualsiasi membro non statico della tua classe e devi restare con i puntatori a funzione, ad esempio, perché la funzione fa parte di un'interfaccia C, la tua migliore opzione è quella di passare sempre a void*
alla tua funzione prendendo puntatori di funzione e chiamando il membro tramite una funzione di inoltro che ottiene un oggetto da void*
e quindi chiama la funzione membro.
In una corretta interfaccia C ++ potresti voler dare un'occhiata al fatto che la tua funzione prenda un argomento basato su modelli per gli oggetti funzione per usare tipi di classe arbitrari. Se l'utilizzo di un'interfaccia basata su modelli non è desiderabile, dovresti usare qualcosa di simile std::function<void(int, int)>
: puoi creare un oggetto funzione richiamabile in modo appropriato per questi, ad esempio, using std::bind()
.
Gli approcci indipendenti dai tipi che utilizzano un argomento modello per il tipo di classe o uno adatto std::function<...>
sono preferibili rispetto all'utilizzo di void*
un'interfaccia poiché rimuovono il potenziale di errori dovuti a un cast al tipo sbagliato.
Per chiarire come utilizzare un puntatore a funzione per chiamare una funzione membro, ecco un esempio:
// the function using the function pointers:
void somefunction(void (*fptr)(void*, int, int), void* context) {
fptr(context, 17, 42);
}
void non_member(void*, int i0, int i1) {
std::cout << "I don't need any context! i0=" << i0 << " i1=" << i1 << "\n";
}
struct foo {
void member(int i0, int i1) {
std::cout << "member function: this=" << this << " i0=" << i0 << " i1=" << i1 << "\n";
}
};
void forwarder(void* context, int i0, int i1) {
static_cast<foo*>(context)->member(i0, i1);
}
int main() {
somefunction(&non_member, 0);
foo object;
somefunction(&forwarder, &object);
}