Problema con el puntero a una función miembro
-
26-09-2019 - |
Pregunta
En el código de abajo (ver comentario):
#include "stdafx.h"
#include <iostream>
using std::cout;
struct Base
{
void fnc()
{
cout << "Base::fnc()";
}
};
struct Impl
{
void* data_;
Impl(void (Base::*fp)())
{
fp();//HERE I'M INVOKING IT - I'M DOING SOMETHING WRONG!
}
};
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
Error
"Error 1 Error C2064: término no se evalúa a una toma de función 0 argumentos"
¿Por qué no funciona y cómo solucionarlo?
Solución
typedef int (MyClass::*memberPointer_t)(int);
...
memberPointer_t mb = &MyClass::function;
MyClass* object = getObject();
int returnValue = (object->*mb)(3);
...
Ya que es un puntero a una función miembro, usted debe llamar a un objeto y utilizar el -..> * O * el operador llamarlo
Otros consejos
No funciona porque fp
no es un puntero de función, sino un puntero miembro.
¿Cómo solucionarlo es fácil, lo utilizan, ya que se debe utilizar: someinstance.*fp();
El problema es que está llamando a la función como una función libre, cuando no lo es. Es una función miembro, y hay que llamar en el contexto de un objeto:
(obj.*f)();
Boost.Bind ofrece una forma idiomática para hacer frente a esto:
#include<boost/bind.hpp>
// ...
Impl i(boost::bind(&Base::fnc, obj));
Se puede definir el constructor Impl
este modo:
#include<boost/function.hpp>
// ...
Impl(boost::function<void ()> fnc)
{
fnc(); // boost::bind translates it to obj.fnc()
}
Si sólo el objeto Impl
sabe lo que se oponga a llamar a la función, a continuación, puede utilizar los marcadores de posición de Boost.Bind:
Impl i(boost::bind(&Base::fnc, boost::_1));
Y el constructor Impl
sería entonces similar a
Impl(boost::function<void (Base)> fnc, Base& b)
{
fnc(b); // boost::bind translates it to b.fnc()
}
A veces es más prudente utilizar plantillas en el lado que acepta el functor:
template<class Op>
Impl(Op fnc) { ... }
ya continuación, el cliente puede pasar cualquier función miembro, con o sin impulso. Pero el costo es que es posible que tenga más difícil de entender compilador mensajes de error.
Se necesita una base para llamar a la función.
podría estar buscando algo más parecido a bind () y la función <> que le permitirá enlazar una función miembro de instancia y en un funtor que puede ser llamado simplemente como una función.
Se podría beneficiarse de la lectura este respecto FAQ punteros a funciones miembro. En particular, se recomienda encarecidamente a definir una macro para estas llamadas:
#define CALL_MEMBER_FN(object,ptrToMember) ((object).*(ptrToMember))