tipos sirven resueltos que punteros para los funciones estructura ejercicios definicion datos con arreglos apuntadores c++ function pointers

c++ - sirven - punteros y arreglos en c



¿Cómo almacenar métodos como punteros de función en un contenedor de mapas? (4)

Quiero poder llamar a funciones basadas en los datos que leo del archivo. Así que para cada tipo de elemento, quiero llamar al método de lectura deseado. Escribí este código, pero no se compila donde quiero agregar punteros de función al mapa. ¿Qué está mal?

#include <vector> #include <map> #include <iostream> class reader { std::map< std::string, void(*)()> functionCallMap; // function pointer void readA(){ std::cout << "reading A/n";}; void readB(){ std::cout << "reading B/n";};; public: reader() { *functionCallMap["A"] = &reader::readA;* *functionCallMap["B"] = &reader::readB;* } void read() { auto (*f) = functionCallMap["A"]; (*f)(); } };

Estoy llenando el mapa en Constructor.


Hay dos respuestas hasta ahora, this y this .

La diferencia obvia es que uno usa std::function y otro usa punteros de función. ¡Esta no es la diferencia importante!

El punto clave es que las funciones miembro son funciones miembro no estáticas . Por lo tanto, no son de tipo void() .

Son de tipo void(reader::*)() . Por lo tanto, solo pueden llamarse si un objeto de tipo es un lector dado; Uno puede entender esto de alguna manera como un parámetro oculto.

La this solo soluciona el problema especificando el tipo correcto . Esto se puede hacer usando los punteros de función (como se presentan) o usando la std::function (¡esta última es mucho más costosa!).

La this soluciona el problema vinculando el puntero a la función a la instancia particular de la clase. Después de la vinculación, el tipo es entonces void() . Esto no se puede hacer usando punteros de función sin formato (porque solo pueden apuntar a una función y no a un objeto / par de funciones).


Necesitas usar punteros para funciones miembro, como esto:

class reader { using FuncPtr = void(reader::*)(); // function pointer std::map< std::string, FuncPtr> functionCallMap; void readA(){ std::cout << "reading A/n"; } void readB(){ std::cout << "reading B/n"; } public: reader() { functionCallMap["A"] = &reader::readA; functionCallMap["B"] = &reader::readB; } void read() { auto f = functionCallMap["A"]; (this->*f)(); } }; int main() { reader r; r.read(); }


Puedes usar std::function con lambda o std::bind :

class reader { std::map<std::string, std::function<void()>> functionCallMap; void readA() { std::cout << "reading A/n"; }; void readB() { std::cout << "reading B/n"; }; public: reader() { functionCallMap["A"] = [this]() { readA(); }; functionCallMap["B"] = std::bind(&reader::readB, this); } void read() { functionCallMap["A"](); functionCallMap["B"](); } };


Terminé con esta solución. Hace el trabajo, pero tengo algunas dudas sobre su estética. De todos modos, para resumir, acabé con este código:

#include <map> #include <iostream> #include <functional> class reader { std::map< std::string, std::function<void(std::string tableName)>> functionCallMap; // function pointer void readA(const std::string tableName){ std::cout << "reading:" << tableName<< "/n"; } void readB(const std::string tableName){ std::cout << "reading:" << tableName <<"/n"; } public: reader() { functionCallMap["A"] = std::bind(&reader::readA, this, std::placeholders::_1); functionCallMap["B"] = std::bind(&reader::readA, this, std::placeholders::_1); } void read() { const std::string table_name = "A"; functionCallMap[table_name](table_name); } }; int main() { reader r; r.read(); }

Paso el nombre de la tabla al lector, está bien hecho con el enlace y el marcador de posición .