C++ 中的简单事件系统

2024-02-19

我正在为我的游戏引擎设计一个简单的事件系统。 我想实现以下事件调度程序接口:

// 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();

我想,我需要在调度程序中使用某种包装结构来保存 [Object, pFunc] 对。

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

我不知道如何实现成员函数指针逻辑。 由于我需要它作为实时系统,因此我希望有一个相对快速的解决方案。我感谢所有的建议。

我宁愿避免使用第三方库。


根据评论,您可以使用std::function或类似于所提议的结构here http://blog.molecular-matters.com/2011/09/19/generic-type-safe-delegates-and-events-in-c/.
它遵循第二个建议的最小可行示例:

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();
};

请注意,它必须根据您的要求进行相应修改(目前,目标成员方法没有返回值并且不接受参数)。
此外,它可以轻松扩展以存储目标成员方法的数组,这就是您所寻找的:只需存储成对的向量instances and invoke功能。
此外,您可以将可变参数模板与Dispatcher功能使其更加灵活。这样,您就可以定义Dispatcher具有不同的返回类型和参数列表。

EDIT

它遵循一个示例Dispatcher接受多个目标成员函数。
通过如上所述的可变参数模板来扩展它仍然很容易。

#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一旦实际使用仍然有效。您应该关注绑定对象的生命周期,或者稍微修改示例以引入更安全的句柄。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 中的简单事件系统 的相关文章

  • C# 锁(mylocker) 不起作用

    我有很多 Web 服务调用 异步 在回调中 我会将结果绘制到 Excel 中 我想同步绘图方法 所以我使用以下内容 但是 从我在 Visual Studio 中追踪到 每次 lock locker 都会成功 并且有许多线程运行clearco
  • Excel的解析路径

    其实我想问以下问题 对于位于 目录中定义的 PATH 怎么能 我找出这些目录中的哪个 找到了 因为我需要使用 Process Run 从 C 运行 Excel 并且只需指示 Excel 即可正常工作 Windows 似乎知道在哪里可以找到它
  • C++11 中具有 C 链接的复杂类型

    我需要将 C 库的标头包含到我的 C 11 代码中 现在 标头提供了涉及大量的例程和数据结构double complex到处都是 例如 include
  • 使用 C# 和反射打印完整的对象图

    我有一个复杂的对象 class A int Field1 int field2 property ClassB ClassB property classC classC etc etc 我想使用反射打印完整的对象图 有什么好的代码吗 一种
  • 从 C++ 中的函数返回二维数组[重复]

    这个问题在这里已经有答案了 可能的重复 C 从函数返回多维数组 https stackoverflow com questions 3716595 c returning multidimension array from function
  • 如何正确实现带有 close 方法的处置模式(CA1063)

    框架设计指南 第二版 第 327 页 说 考虑提供方法Close 除了Dispose 如果接近 是该领域的标准术语 这样做时 重要的是使 Close 实现与Dispose并考虑实施IDisposable Dispose方法明确 因此 按照提
  • 如何有效地左填充字节数组

    假设我有一个数组 LogoDataBy byte 0x00000008 0x00000000 0x41 0x00000001 0x42 0x00000002 0x43 0x00000003 0x44 0x00000004 0x31 0x00
  • 如何在方法模板中使用模板类型的引用传递参数?

    我目前正在努力编译以下代码 首先是包含带有方法模板的类的头文件 ConfigurationContext h class ConfigurationContext public template
  • 用于轻松动态反射的 C# 库

    是否有任何库 例如开源项目等 可以更轻松地使用复杂的反射 例如动态创建对象或类 检查实例等 Thanks 有一个LinFu http www codeproject com KB cs LinFuPart1 aspx可用的库除了反射之外还可
  • DataGridView小数不排序

    好吧 我有一个 DataGridView 它的数据绑定如下 dataGridViewChartOre AutoGenerateColumns false dataGridViewChartOre DataSource xml GetOreC
  • Apple IOS 上的 C# 应用程序 [已关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我有基于 C Net 的应用程序 有什么方法可以在 Apple IOS 上运行这些应用程序吗 我没有资
  • 获取进程的所有 DLL

    我想获取为给定进程加载的所有 dll 的列表 我目前正在使用 NET框架4 0 我知道有一个bug https connect microsoft com VisualStudio feedback details 546430 syste
  • 关于 FirstOrDefault 或 SingleOrDefault

    FirstOrDefault 或 SingleOrDefault 将返回什么类型的数据 假设我的查询返回 3 条记录 例如 empid ename salary 1 joy 1500 2 rob 4500 3 jen 6500 所以如果我们
  • 如何使用 Linq to Sql 修剪值?

    在数据库中 我有一个名为 联系人 的表 名字和其他此类字符串字段设计为使用 Char 数据类型 不是我的数据库设计 我的对象 Contact 映射到属性中的字符串类型 如果我想做一个简单的测试 通过 id 检索 Contact 对象 我会这
  • 为什么这段代码不会产生编译错误?

    template
  • 当一种语言是另一种语言的平行超集时,这意味着什么?

    我正在阅读关于实时并发 C 的期刊文章 http link springer com article 10 1007 2FBF00365999 并且它在摘要中提到 因此你们中的任何人都可以通过该链接查看上下文 Concurrent C 是
  • 在 Ubuntu 16.04 上编译 PCL 1.7,CMake 生成的 Makefile 中出现错误

    我正在尝试让 PCL 1 7 点云库 而不是其他 pcl 在 Ubuntu 16 04 上运行 我最终希望用于 C 的东西 但现在我只是想让这些例子工作 我使用的是 Ubuntu GNU 5 3 1 附带的默认编译器和 Cmake 版本 3
  • 为什么 g++ 在编译的二进制文件中存储类名?

    我注意到如果我跑strings在我编译的程序上g 输出包含它使用的各种类的名称 该程序是用 O3并且没有 g or p 并且当我剥离二进制文件时 类名仍然存在 我想知道为什么有必要g 将此信息存储在二进制文件中 出现的类名似乎都是使用虚函数
  • 通过开源 PCL 使用 API 查看 3D 点云

    我使用 ToF 飞行时间 相机来获取 XYZ 格式的深度数据 为了实现 3D 点云的可视化目的 我想使用开源 PCL 提供的 API 网址为http pointclouds org documentation tutorials pcl v
  • 如何正确对齐 WPF GeometryGroup 中的路径?

    我正在使用一个GeometryGroup在圆的中心绘制一个符号 下面的示例显示了我在对此进行实验时的尝试之一 它具有从同一原点 32 32 出发的三条直线

随机推荐