如何使用 std::bind 将会员回调添加到信使系统

How to use std::bind for adding member callback to a messenger system

我目前正在尝试为我的游戏引擎实现一个消息系统。它使用以下形式的函数回调:

typedef std::function<void(const Message &)> Callback;

我希望所有对象都能够订阅特定类型的消息(其中类型只是一个字符串)。订阅意味着将它们的 "onEvent" 函数添加到回调字典中。

mutable std::map<std::string, std::vector<Callback>> callbackDictionary;

更新函数然后调用这些函数并传递相应的消息("onEvent" 函数可以从中获取数据)

for each (auto message in messageList)
{
    // find the list of respective callbacks
    auto it = callbackDictionary.find(message->GetType());

    // If there are callbacks registered for this message type
    if (it != callbackDictionary.end())
    {
        // call every registred callback with the appropreate message
        for each (auto callback in it->second)
            callback(*message);
    }
}

现在,我的问题是我不太确定如何绑定这些 "onEvent" 函数。我最近刚切换到 C++11,函数对象和 std::bind 的概念对我来说很新。所以这是我尝试过的:

messageBus.Subscribe("Message/Click",std::bind(&ClickableComponent::OnClick, this));

其中 ClickableComponent::OnClick 函数具有所需的签名:

void OnClick(const Message &);

而订阅函数只是将传递的函数添加到字典中

void Messenger::Subscribe(std::string type, Callback callbackFunction) const
{
    callbackDictionary[type].push_back(callbackFunction);
}

(使用push_back是因为每种类型都有一个回调向量)

代码对我来说似乎很好,但是行:

messageBus.Subscribe("Message/Click", std::bind(&ClickableComponent::OnClick, this));

给我错误: picture of the error discription

我已经尝试了各种方法,例如转发 Messenger 引用和使用占位符,但我感觉我做错了什么。另外,关于如何实现这个信使系统的更好的想法表示赞赏^^

感谢您的帮助!

std::bind 在您的情况下不是必需的,lambda 函数就可以了:

messageBus.Subscribe("Message/Click", [this](const Message& msg) { OnClick(msg); });

std::bind 在元编程的特定情况下更有用。

但如果你有足够的好奇心想知道如何使用 std::bind:

messageBus.Subscribe("Message/Click", 
    std::bind(&ClickableComponent::OnClick, this, std::placeholders::_1));

在这里,如您所见,您错过了 std::placeholders::_1。你的仿函数签名是void(const Message&),但你试图存储一个成员函数,其签名可以被视为void(ClickableComponent*, const Message&)。要部分应用某些参数(std::bind 所做的),您需要指定要绑定的参数和未绑定的参数。

首选 Lambda,因为它通常更短、更灵活且更易读。