gpt4 book ai didi

C++:如何构建没有空指针的事件/消息系统?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:10:19 25 4
gpt4 key购买 nike

我想在我的 C++ 项目中有一个动态消息系统,其中有一个固定的现有事件列表,事件可以在运行时的任何地方触发,并且您可以在其中订阅特定事件的回调函数。

在这些事件中传递的参数应该有一个选项。例如,一个事件可能不需要任何参数 (EVENT_EXIT),有些事件可能需要多个参数 (EVENT_PLAYER_CHAT: Player object pointer, String with message)

使这成为可能的第一个选项是允许在触发事件时将空指针作为参数传递给事件管理器,并在回调函数中接收它。

虽然:我被告知 void 指针是不安全的,我不应该使用它们。

  • 如何在不使用 void 指针的情况下为我的事件保留(半)动态参数类型和计数?

最佳答案

由于其他人提到了访问者模式,这里使用 Boost.Variant 稍微改变一下。 .当您需要一组基于值的不同行为时,这个库通常是一个不错的选择(或者至少对我来说是这样)。与 void* 相比,它具有静态类型检查的好处:如果您编写的访问者类遗漏了其中一种情况,您的代码将无法编译而不是在运行时失败。

第 1 步:定义消息类型:

struct EVENT_EXIT { }; // just a tag, really
struct EVENT_PLAYER_CHAT { Player * p; std::string msg; };

typedef boost::variant<EVENT_EXIT,
EVENT_PLAYER_CHAT> event;

第 2 步:定义访问者:

struct event_handler : public boost::static_visitor<void> {
void operator()(EVENT_EXIT const& e) {
// handle exit event here
}

void operator()(EVENT_PLAYER_CHAT const& e) {
// handle chat event here
std::cout << e.msg << std::endl;
}
};

这定义了一个事件处理程序,可以很好地分离出每种事件的代码。所有的存在operator()重载在编译时检查(在模板实例化时),因此如果您稍后添加事件类型,编译器将强制您添加相应的处理程序代码

请注意 event_handler子类 boost::static_visitor<void> .这决定了每个 operator() 的返回类型过载。

第 3 步:使用您的事件处理程序:

event_handler handler;
// ...
event const& e = get_event(); //variant type
boost::apply_visitor(handler, e); // will not compile unless handler
// implements operator() for each
// kind of event

在这里,apply_visitor将为 e 的“实际”值调用适当的重载.例如,如果我们定义 get_event如下:

event get_event() {
return EXIT_EVENT();
}

然后返回值会被隐式转换为event(EXIT_EVENT()) .那么apply_visitor会调用对应的operator()(EXIT_EVENT const&)过载。

关于C++:如何构建没有空指针的事件/消息系统?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5370171/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com