c++ - 消息系统 : Callbacks can be anything

标签 c++ event-handling boost-bind

我正在尝试为我的游戏编写一个事件系统。我的事件管理器将存储的回调既可以是普通函数也可以是仿函数。我还需要能够比较函数/仿函数,以便我知道我需要断开与事件管理器的连接。

• 最初我尝试使用 boost::function;它可以很好地处理函数和仿函数,除了它没有运算符==,所以如果我想的话我不能删除回调。

class EventManager
{
    typedef boost::function<void (boost::weak_ptr<Event>)> Callback;
    std::map<Event::Type, std::vector<Callback>> eventHandlerMap_;
};

• 我也尝试过使用 boost::signal,但这也给了我一个与运算符==相关的编译问题:

binary '==' : no operator found which takes a left-hand operand of type 'const Functor' (or there is no acceptable conversion)

void test(int c) {
    std::cout << "test(" << c << ")";
}

struct Functor
{
    void operator()(int g) {
        std::cout << "Functor::operator(" << g << ")";
    }
};

int main()
{
    boost::signal<void (int)> sig;

    Functor f;

    sig.connect(test);
    sig.connect(f);

    sig(7);

    sig.disconnect(f); // Error
}

关于我如何实现这个的任何其他建议?或者我怎样才能使 boost::function 或 boost::signal 工作? (虽然我宁愿使用 boost::函数,因为我听说对于小的项目集合信号相当慢。)


编辑:这是我希望 EventManager 拥有的界面。

class EventManager
{
  public:
    void addEventHandler(Event::Type evType, Callback func);
    void removeEventHandler(Event::Type evType, Callback func);

    void queueEvent(boost::shared_ptr<Event> ev);
    void dispatchNextEvent();
};

最佳答案

您会发现大多数通用函数包装器不支持函数相等性。

这是为什么?好吧,看看你的仿函数:

struct Functor
{
    void operator()(int g) {
        std::cout << "Functor::operator(" << g << ")";
    }
};

这个 Functor 没有 operator==,因此不能比较是否相等。因此,当您将它传递给 boost::signal 按值 时,将创建一个新实例;这将为指针相等性比较 false,并且没有运算符来测试值相等性。

事实上,大多数仿函数没有值相等谓词。这不是很有用。处理这个问题的通常方法是改为拥有回调的句柄; boost::signals 用它的 connection 对象来做这件事。例如,查看来自 the documentation 的示例:

boost::signals::connection c = sig.connect(HelloWorld());
if (c.connected()) {
// c is still connected to the signal
  sig(); // Prints "Hello, World!"
}

c.disconnect(); // Disconnect the HelloWorld object
assert(!c.connected()); c isn't connected any more

sig(); // Does nothing: there are no connected slots

有了这个,HelloWorld 就不需要 operator==,因为您直接指的是信号注册。

关于c++ - 消息系统 : Callbacks can be anything,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6884041/

相关文章:

jquery - 删除子项的事件处理程序

javascript - React – 将事件从子组件传递到父组件

Javascript - 事件处理程序中的变量范围

c++ - 如何仅使用 OpenCV C++ 中的 *.lib 文件而不是 *.dll

c++ - 这里应用了哪个重载决议规则?

c++ - "using namespace std;"没有任何#include?

c++ - 在没有组合的情况下对嵌套的 boost::bind 执行参数替换

boost - 使用 boost::asio::io_service::post()

c++ - 如何在 C++ 中安全地销毁 Posix 线程池

c++ - 将 gcc 构建的 Boost 链接到英特尔 C++ 编译程序时静态初始化期间的段错误