我正在尝试创建一个在游戏中使用的非常简单的事件系统。我有一个类似于这样的EventManager类:
typedef std::function<void(IEvent* event)> CallbackType;
class EventManager
{
public:
void AddListener(const std::string eventName, IEventListener* listener)
{
CallbackType callback = std::bind(&IEventListener::HandleEvent, listener, std::placeholders::_1);
listeners[eventName].push_back(callback);
}
void AddListener(const std::string eventName, CallbackType callback)
{
// ...
}
void TriggerEvent(IEvent* event)
{
for (CallbackType callback : listeners[event->GetName()])
{
callback(event);
}
}
private:
std::map<std::string, std::vector<CallbackType>> listeners;
}
第一个AddListener函数完美运行。 TriggerEvent函数调用HandleEvent函数,该函数由扩展我的IEventListener接口的每个类实现。
我真的希望能够将回调传递给第二个AddListener函数。然后像以前一样在TriggerEvent函数中调用此回调。我可以传入一个使用std :: bind构造的回调,这是有效的。例如:
eventManager->AddListener("WindowResize", std::bind(&MyClass::MemberFunction, this, std::placeholders::_1));
其中MyClass扩展了IEventListener接口。但是,我真的希望能够只传递一个简单的函数指针:
eventManager->AddListener("WindowResize", this, &MyClass::MemberFunction);
这可能吗?
对于任何有兴趣的人,我写了一些宏,我认为这些宏会让事情变得更清洁。
#define MEMBER_CALLBACK(funPtr) \
std::bind(&funPtr, this, std::placeholders::_1)
#define MEMBER_CALLBACK_WITH_INSTANCE(funPtr, instancePtr) \
std::bind(&funPtr, instancePtr, std::placeholders::_1)
现在我可以通过以下方式订阅活动:
eventManager->AddListener("EventName", MEMBER_CALLBACK(MyClass::MemberFunction));
答案 0 :(得分:2)
您无法传递简单的函数指针,因为MyClass::MemberFunction
不是一个简单的函数。 std::bind()
有效,因为它将MyClass
的实例与对成员函数的引用相关联。如果没有该信息,成员函数将无法访问实例的数据。