utilice sintaxis que punteros puntero ptr para miembro funcion estándar crear clase c++ function-pointers member-function-pointers

sintaxis - Pasar el puntero a la función miembro al objeto miembro en c++



sintaxis no estándar utilice ''&'' para crear un puntero a miembro (4)

Tengo un problema con el uso de un puntero para funcionar en C ++. Aquí está mi ejemplo:

#include <iostream> using namespace std; class bar { public: void (*funcP)(); }; class foo { public: bar myBar; void hello(){cout << "hello" << endl;}; }; void byebye() { cout << "bye" << endl; } int main() { foo testFoo; testFoo.myBar.funcP = &byebye; //OK testFoo.myBar.funcP = &testFoo.hello; //ERROR return 0; }

El testFoo.myBar.funcP = &testFoo.hello; devuelve un error en testFoo.myBar.funcP = &testFoo.hello; :

ISO C ++ prohíbe tomar la dirección de una función miembro vinculada para formar un puntero a la función miembro. Di ''& foo :: hola''

no se puede convertir ''void (foo ::) ()'' a ''void ( ) ()'' en la asignación

Así que lo intenté así:

class bar { public: void (*foo::funcP)(); };

Pero ahora el compilador añade uno más:

''foo'' no ha sido declarado

¿Hay alguna manera de hacerlo funcionar?

Gracias de antemano por las sugerencias


Como dice el error, los métodos pertenecen a la clase, no a instancias individuales. Por esta razón, los punteros a funciones libres y los punteros a métodos no estáticos son cosas completamente diferentes. También necesitarás una instancia para activar el método.

//declaring and taking the address of a foo''s method void (foo::*method)() = &foo::hello; //as the compiler nicely suggests //calling a function through pointer free_func(); //calling a method through pointer foo instance; (instance.*method)();

Puede usar bibliotecas como Boost.Bind y Boost.Function (también en std :: tr1, creo) para abstraer la diferencia y también vincular una instancia al método:

#include <iostream> #include <boost/bind.hpp> #include <boost/function.hpp> using namespace std; class foo { public: void hello(){cout << "hello" << endl;}; }; void byebye() { cout << "bye" << endl; } int main() { foo testFoo; boost::function<void()> helloFunc(boost::bind(&foo::hello, testFoo)); boost::function<void()> byeFunc(byebye); helloFunc(); byeFunc(); return 0; }


Para hacer que su segunda opción funcione, declare foo para que el compilador sepa que es una clase.

También tenga en cuenta que su sintaxis de puntero de función es incorrecta. El * viene justo antes del nombre de la variable:

class foo; class bar { public: void (foo::*funcP)(); };


Reenviar la declaración de Foo frente a la barra:

class foo;


Tomando las sugerencias de todos juntos, su solución final se verá así:

#include <iostream> using std::cout; usind std::endl; class foo; // tell the compiler there''s a foo out there. class bar { public: // If you want to store a pointer to each type of function you''ll // need two different pointers here: void (*freeFunctionPointer)(); void (foo::*memberFunctionPointer)(); }; class foo { public: bar myBar; void hello(){ cout << "hello" << endl; } }; void byebye() { cout << "bye" << endl; } int main() { foo testFoo; testFoo.myBar.freeFunctionPointer = &byebye; testFoo.myBar.memberFunctionPointer = &foo::hello; ((testFoo).*(testFoo.myBar.memberFunctionPointer))(); // calls foo::hello() testFoo.myBar.freeFunctionPointer(); // calls byebye() return 0; }

El C ++ FAQ Lite tiene una guía sobre cómo simplificar la sintaxis.

Tomando la idea de Chris y ejecutándola, podrías conseguir algo como esto:

#include <iostream> using std::cout; using std::endl; class foo; typedef void (*FreeFn)(); typedef void (foo::*MemberFn)(); class bar { public: bar() : freeFn(NULL), memberFn(NULL) {} void operator()(foo* other) { if (freeFn != NULL) { freeFn(); } else if (memberFn != NULL) { ((other)->*(memberFn))(); } else { cout << "No function attached!" << endl; } } void setFreeFn(FreeFn value) { freeFn = value; memberFn = NULL; } void setMemberFn(MemberFn value) { memberFn = value; freeFn = NULL; } private: FreeFn freeFn; MemberFn memberFn; }; class foo { public: bar myBar; void hello() { cout << "foo::hello()" << endl; } void operator()() { myBar(this); } }; void bye() { cout << "bye()" << endl; } int main() { foo testFoo; testFoo(); testFoo.myBar.setMemberFn(&foo::hello); testFoo(); testFoo.myBar.setFreeFn(&bye); testFoo(); return 0; }