No hay nada de malo en usar punteros de función. Sin embargo, los punteros a funciones miembro no estáticas no son como los punteros de función normales: las funciones miembro deben llamarse en un objeto que se pasa como un argumento implícito a la función. La firma de su función miembro anterior es, por lo tanto
void (aClass::*)(int, int)
en lugar del tipo que intentas usar
void (*)(int, int)
Un enfoque podría consistir en hacer que el miembro funcione, static
en cuyo caso no requiere invocar ningún objeto y puede usarlo con el tipo void (*)(int, int)
.
Si necesita acceder a cualquier miembro no estático de su clase y necesita seguir con punteros de función, por ejemplo, debido a que la función es parte de una interfaz C, su mejor opción es pasar siempre void*
a su función tomando punteros de función y llamando su miembro a través de una función de reenvío que obtiene un objeto del void*
y luego llama a la función miembro.
En una interfaz C ++ adecuada, es posible que desee ver cómo su función toma un argumento con plantilla para que los objetos de función usen tipos de clase arbitrarios. Si el uso de una interfaz con plantilla no es deseable, debe usar algo como std::function<void(int, int)>
: puede crear un objeto de función invocable adecuadamente para estos, por ejemplo, usando std::bind()
.
Los enfoques de tipo seguro que utilizan un argumento de plantilla para el tipo de clase o un tipo adecuado std::function<...>
son preferibles que el uso de una void*
interfaz, ya que eliminan la posibilidad de errores debido a una conversión al tipo incorrecto.
Para aclarar cómo usar un puntero de función para llamar a una función miembro, aquí hay un ejemplo:
// 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);
}