C ++中的简单事件系统 [英] Simple event system in C++

查看:145
本文介绍了C ++中的简单事件系统的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为我的游戏引擎设计简单的事件系统。
我想实现以下事件分派器接口:

Im designing simple event system for my game engine. I want too implement following event dispatcher interface:

// Create event dispatcher.
Dispatcher dispatcher;

// Create objects b and c.
// Created objects extend base A class.
A* b = new B();
A* c = new C();

// Register b and c in dispatcher.
// I guess I should also pass member function pointer,
// but I am not sure how to do it.
// Like this; dispatcher.Add(b, &B::DoWork) ?
// Member function that I want to accept is always bool func(/*no params*/)
dispatcher.Add(b /*, member function pointer?*/);
dispatcher.Add(c /*, member function pointer?*/);

// Trigger passed functions for registered objects.
dispatcher.Trigger();

我想,我需要在Dispatcher中有一些包装结构,用来保存[pObject,pFunc]

I guess, Im gonna need some kind of wrapper struct inside Dispatcher, to hold [pObject, pFunc] pair.

struct Wrapper
{
   A* pObj; // Of base class A.
   // ??    // Pointer to given member function of A.
};

我不知道如何实现成员函数指针逻辑。
由于我需要它的实时系统,我想你提出相对快的解决方案。我将感谢所有建议。

I dont know how to implement member function pointer logic. As I need it for real time system, I would like You to propose relatively fast solution. I will appreciate all suggestions.

我只使用STL。

推荐答案

根据注释,您可以使用 std :: function 或类似于建议的此处

它遵循最小和第二个建议的工作示例:

According with the comments, you can use either std::function or a structure similar to the one proposed here.
It follows a minimal and working example of the second suggestion:

class Dispatcher {
    Dispatcher() { }

    template<class C, void(C::*M)() = C::receive>
    static void invoke(void *instance) {
        (static_cast<C*>(instance)->*M)();
    }

public:
    template<class C, void(C::*M)() = &C::receive>
    static Dispatcher create(C *instance) {
        Dispatcher d;
        d.fn = &invoke<C, M>;
        d.instance = instance;
        return d;
    }

    void operator()() {
        (fn)(instance);
    }

private:
    using Fn = void(*)(void *);
    Fn fn;
    void *instance;
};

struct S {
    void receive() { }
};

int main() {
    S s;
    Dispatcher d = Dispatcher::create(&s);
    d();
};

请注意,它必须根据您的要求进行相应修改(目前,目标成员方法没有返回值并且不接受参数)。
$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ c> instance s和 invoke 函数。

此外,您可以使用variadic模板与 Dispatcher 函数让它更灵活。这样,您就可以定义具有不同返回类型和参数列表的 Dispatcher

Note that it has to be modified accordingly with your requirements (currently, the targeted member method has no return value and does not accept arguments).
Also, it can be easily extended to store an array of target member methods, that is what you were looking for: simply store a vector of pairs of instances and invoke functions.
In addition, you can use variadic template with the Dispatcher function to let it be more flexible. This way, you'll be able to define Dispatchers having different return types and arguments lists.

EDIT

它遵循接受多个目标成员函数的 Dispatcher 示例。

如上所述,通过可变参数模板扩展它仍然很容易。

It follows an example of a Dispatcher that accepts more than one target member function.
To extend it by means of variadic template as above mentioned is still quite easy.

#include <vector>
#include <utility>

class Dispatcher { 
    template<class C, void(C::*M)() = C::receive>
    static void invoke(void *instance) {
        (static_cast<C*>(instance)->*M)();
    }

public:
    template<class C, void(C::*M)() = &C::receive>
    void bind(C *instance) {
        auto pair = std::make_pair(&invoke<C, M>, instance);
        targets.push_back(pair);
    }

    void operator()() {
        for(auto pair: targets) {
            (pair.first)(pair.second);
        }
    }

private:
    using Fn = void(*)(void *);
    std::vector<std::pair<Fn, void*>> targets;
};

struct S {
    void receive() { }
};

struct T {
    void receive() { }
};

int main() {
    S s;
    T t;
    Dispatcher d;
    d.bind(&s);
    d.bind(&t);
    d();
};

请注意,在上面的示例中,不能保证指针以 instance 在实际使用后仍然有效。您应该考虑绑定对象的生命周期,或者稍微修改示例,以便引入一个更安全的句柄。

Please note that in the examples above there is no guarantee that the pointer submitted as instance is still valid once actually used. You should either take care of the lifetime of your bound objects or slightly modify the example in order to introduce a more safer handle.

这篇关于C ++中的简单事件系统的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆