c++ - resueltos - miembros de una clase en programacion orientada a objetos
Uso de objetos genéricos std:: function con funciones miembro en una clase (3)
Para una clase, quiero almacenar algunos punteros a funciones miembro de la misma clase en un map
almacena objetos std::function
. Pero fallo al principio con este código:
class Foo {
public:
void doSomething() {}
void bindFunction() {
// ERROR
std::function<void(void)> f = &Foo::doSomething;
}
};
Recibo el error C2064: term does not evaluate to a function taking 0 arguments
en xxcallobj
combinado con algunos errores extraños de xxcallobj
instancias de plantillas. Actualmente estoy trabajando en Windows 8 con Visual Studio 2010/2011 y en Win 7 con VS10 también falla. El error debe basarse en algunas reglas raras de C ++ que no sigo.
EDITAR: NO uso boost. Esto es C ++ 11 integrado en el compilador de MS.
O necesitas
std::function<void(Foo*)> f = &Foo::doSomething;
para que pueda llamarlo en cualquier instancia, o necesita vincular una instancia específica, por ejemplo, this
std::function<void(void)> f = std::bind(&Foo::doSomething, this);
Si necesita almacenar una función de miembro sin la instancia de clase, puede hacer algo como esto:
class MyClass
{
public:
void MemberFunc(int value)
{
//do something
}
};
// Store member function binding
auto callable = std::mem_fn(&MyClass::MemberFunc);
// Call with late supplied ''this''
MyClass myInst;
callable(&myInst, 123);
¿Cómo se vería el tipo de almacenamiento sin auto ? Algo como esto:
std::_Mem_fn_wrap<void,void (__cdecl TestA::*)(int),TestA,int> callable
También puede pasar este almacenamiento de función a un enlace de función estándar
std::function<void(int)> binding = std::bind(callable, &testA, std::placeholders::_1);
binding(123); // Call
Notas pasadas y futuras: existía una interfaz anterior, std :: mem_func , pero desde entonces ha quedado obsoleta. Existe una propuesta, publicar C ++ 17, para hacer que las funciones de puntero a miembro sean llamables . Esto sería muy bienvenido.
Una función miembro no estática debe invocarse con un objeto. Es decir, siempre implícitamente pasa "este" puntero como argumento.
Debido a que su firma std::function
especifica que su función no toma ningún argumento ( <void(void)>
), debe enlazar el primer (y el único) argumento.
std::function<void(void)> f = std::bind(&Foo::doSomething, this);
Si desea vincular una función con parámetros, debe especificar marcadores de posición:
using namespace std::placeholders;
std::function<void(int,int)> f = std::bind(&Foo::doSomethingArgs, this, _1, _2);
O bien, si su compilador es compatible con C ++ 11 lambdas:
std::function<void(int,int)> f = [=](int a, int b) {
this->doSomethingArgs(a, b);
}
(No tengo un compilador capaz de C ++ 11 en este momento , así que no puedo verificarlo).