c++ - studio - programacion android pdf 2018
Mapa C++ de "eventos" y punteros de funciones de miembros (2)
Logré escribir una clase de plantilla para que funcione como una devolución de llamada, aprendí de la respuesta aceptada de esta pregunta Cómo definir un puntero de función de miembro general .
Deseo tener un mapa de claves de cadena y valores de devolución de llamada para poder invocar la devolución de llamada adecuada que coincida con una cadena. Esto estaría bien, pero necesito el mapa para admitir rellamadas de diferentes clases. En este momento solo puede funcionar con una clase. Puede ser cualquier clase debido a la plantilla, pero solo una colección de devoluciones de llamada de la misma clase.
class Apple {
public:
void Red () {
cout << "aa";
}
};
class Orange {
public:
void Blue () {
cout << "bb";
}
};
template <typename T>
class Callback {
T *obj;
void (T::*ptr) (void);
public:
Callback (T *obj, void (T::*ptr) (void)) : obj (obj), ptr (ptr) {
}
void Call () {
(obj->*ptr) ();
}
};
Puedo usar esto como tal
Apple apple;
Orange orange;
Callback <Apple> callA (&apple, &Apple::Red);
Callback <Orange> callB (&orange, &Orange::Blue);
callA.call ();
callB.call ();
std::map <std::string, Callback <Apple>> appleCallbacks;
Quiero ser capaz de hacer esto
std::map <std::string, Callback <anything>> anyCallbacks;
Planeo usar esto con un conjunto de clases que comparten la misma clase base y tienen funciones idénticas entre sí en la definición, excepto por el nombre y la clase a la que pertenece.
class Base { };
class ChildA : public Base {
public:
void Talk ();
}
class ChildB : public Base {
public:
void Walk ();
}
Entonces, si esto funcionara, podría poner tanto Talk () como Walk () en el mapa.
¿Es esto posible o es mi punto de vista defectuoso para empezar?
La locura miente, de esta manera: no vincula las devoluciones de llamadas a clases específicas. En su lugar, use un objeto std::function<Signature>
y cree objetos de función adecuados: cuando necesite operar en diferentes clases, también deberá operar objetos de diferentes tipos. Usar std::function<...>
debería ser el truco, por ejemplo:
std::map<std::string, std::function<void()>> operations;
operations["talk"] = std::bind(&ChildA::Talk, ChildA());
operations["walk"] = std::bind(&ChildB::Walk, ChildB());
operations["talk"]();
No hay necesidad de herencia aquí. Simplemente use std::function
para almacenar los punteros de la función miembro y std::bind
para unir el puntero de la función miembro y la instancia del objeto.
#include <functional>
#include <map>
#include <string>
#include <iostream>
struct Apple {
void Red () {
std::cout << "aa/n";
}
};
struct Orange {
void Blue () {
std::cout << "bb/n";
}
};
int main()
{
std::map<std::string, std::function<void()>> m;
Apple a;
Orange o;
m["apple"] = std::bind(&Apple::Red, a);
m["orange"] = std::bind(&Orange::Blue, o);
m["apple"]();
m["orange"]();
}
Salida:
aa
bb