5

Quiero almacenar un puntero a un objeto y un puntero a su método de firma conocida. Si sé la clase entonces este tipo de puntero tiene:C++ almacenar un puntero a una función miembro de la clase desconocida

int (MyClass::*pt2Member)(float, char, char) 

Pero, ¿cómo puedo almacenar el puntero si no sé el tipo?

quiero hacer algo como esto:

myObject.callThisFuncLater(&otherObject, &otherObject::method) 

¿Cómo puedo almacenar un puntero a método method en myObject y llamar más tarde?

+1

Seis mil millones de duplicados. – Puppy

+1

@DeadMG: muéstreles :) mi contador está bloqueado en 2,178,933 preguntas totales – sehe

+0

¿Qué argumentos usará cuando lo llame más tarde? – Beta

Respuesta

2

Puede usar boost::function (y boost::bind) para almacenar un fragmento de código que se llamará más tarde.

class MyClass 
{ 
public: 
    void callThisFuncLater(boost::function< int (float, char, char) > callBack); 
}; 
... 
myObject.callThisFuncLater(boost::bind(&otherObject::method, &otherObject)); 
+1

Podría estar equivocado, pero ¿deberían cambiarse '& otherObject' y' & otherObject :: method'? – Vortico

+0

@Vortico Tienes razón, lo siento. Voy a editar mi publicación para corregirla. –

5

La forma más fácil de hacerlo si tiene acceso a las extensiones de la biblioteca STL (TR1 disponibles en gcc y Visual Studio 2008 y en adelante es. Std :: función y std :: bind se pueden utilizar para envolver una . invocación que se puede llamar más tarde Esta funcionalidad también está disponible en función de impulso y de impulso aprieto:.

#include <functional> 

class MyClass { 
public: 
    template<typename T> callThisFuncLater(T& otherObject, 
             int(T::*)(float, char, char) method) { 
    return storedInvocation_ = std::bind(otherObject, 
            method, 
            std::placeholders::_1, // float 
            std::placeholders::_2, // char 
            std::placeholders::_3); // char 
    } 

    int callStoredInvocation(float a, char b, char c) { 
    storedInvocation_(a, b, c); 
    } 

private: 
    std::function<int(float, char, char)> storedInvocation_; 
}; 
-1

Personalmente me gustaría elegir un diseño diferente Simplemente porque los punteros de función miembro de C++ no son fáciles de trabajar con Personalmente. elegiría utilizar interfaces y heredar de estos y analizar a lo largo de éstos.

Uno de los problemas con los punteros de función de miembro es que se implementan de manera diferente en compiladores diferentes. Si usa los compiladores de Borland/Embarcardero y desea limitarse a esto, puede usar la palabra clave __closure, aunque probablemente no lo esté, y por lo tanto tendría que usar alguna otra implementación específica del compilador, o usar uno de los impulsores. clases de ayuda como función.

Pero si se encuentra en una situación en la que le resulta útil utilizar los punteros de función de miembro en C++, reconsidere su diseño.

+0

La alternativa estándar a los cierres son las funciones lambda, pero todavía no es un reemplazo realista para las funciones de los miembros. – MSalters

3

No hay simple forma de hacerlo originalmente construido en el idioma o la biblioteca estándar (aunque recientemente se ha agregado). Si está familiarizado con Boost, incluyen una solución para esto: Boost.Function.

Si por alguna razón, sin embargo, no es capaz o no está dispuesto a usar Boost, hay una manera genérica de hacer esto usando las plantillas (que, sin duda, es bastante similar a la solución de Boost):

class FncPtr 
{ 
public: 
    virtual int call(float, char, char) = 0; 
}; 

template <typename T> 
class ClassFncPtr : public FncPtr 
{ 
    int (T::*pt2Member)(float, char, char); 
    T *inst; 
public: 
    ClassFncPtr(T* who, int (T::*memfunc)(float,char,char)) 
     : inst(who), pt2Member(memfunc) 
    { 
    } 
    int call(float a, char b, char c) 
    { 
     return (inst->*pt2Member)(a,b,c); 
    } 
}; 

template <typename T> 
FncPtr * makeFuncPointer(T* who, int (T::*memfunc)(float,char,char)) 
{ 
    return new ClassFncPtr<T>(who,memfunc); 
} 

También puede crear la subclase FncPtr para poder usar funciones que no sean de clase, si lo desea.

Cuestiones relacionadas