如何在此回调中用具有编译时类型检查的内容替换 void 指针?
我正在尝试创建一个通过回调通知的事件系统。我已经编写了代码,但它依赖于 void 指针才能工作。在我的上一个项目中,空指针对我造成了多大的困扰,我想用编译时类型检查的东西来替换空指针。
这是 Event 类
enum EventType {
TEST_TYPE_A,
TEST_TYPE_B
};
// used by event receivers
class EventHandler
{
public:
virtual void handleEvent(EventType type, void* data) = 0; // PROBLEM HERE
};
// class to send events to objects registered for them
class Event
{
private:
std::multimap<EventType, EventHandler*> eventMap;
public:
void registerForEvent(EventType type, EventHandler *handler) {
eventMap.insert(std::pair<EventType, EventHandler*>(type, handler));
}
void sendEvent(EventType type, void* data) { // PROBLEM HERE
std::multimap<EventType, EventHandler*>::iterator it;
std::pair<std::multimap<EventType, EventHandler*>::iterator, std::multimap<EventType, EventHandler*>::iterator> matches;
matches = eventMap.equal_range(type);
for (it = matches.first; it != matches.second; ++it) {
it->second->handleEvent(type, data);
}
}
};
这是测试 Event 类的代码
class Handler : public EventHandler {
public:
void handleEvent(EventType type, void* data) {
char *cp = (char*)data;
printf("Handler: %s \n", cp);
}
};
int main(int argc, const char* argv[]) {
Handler handle;
Event event;
char c[] = "what?";
event.registerForEvent(TEST_TYPE_A, &handle);
event.sendEvent(TEST_TYPE_A, (void*)c);
return 0;
}
提前感谢您的指点!我有点坚持这个。
I'm trying to create an event system with notifications via callbacks. I have the code written, but it is dependent on void pointers to work. After how hard void pointers bit me in my last project I would like to replace the void pointers with something that compile time type checks.
Here's the Event class
enum EventType {
TEST_TYPE_A,
TEST_TYPE_B
};
// used by event receivers
class EventHandler
{
public:
virtual void handleEvent(EventType type, void* data) = 0; // PROBLEM HERE
};
// class to send events to objects registered for them
class Event
{
private:
std::multimap<EventType, EventHandler*> eventMap;
public:
void registerForEvent(EventType type, EventHandler *handler) {
eventMap.insert(std::pair<EventType, EventHandler*>(type, handler));
}
void sendEvent(EventType type, void* data) { // PROBLEM HERE
std::multimap<EventType, EventHandler*>::iterator it;
std::pair<std::multimap<EventType, EventHandler*>::iterator, std::multimap<EventType, EventHandler*>::iterator> matches;
matches = eventMap.equal_range(type);
for (it = matches.first; it != matches.second; ++it) {
it->second->handleEvent(type, data);
}
}
};
And here's the code to test the Event class
class Handler : public EventHandler {
public:
void handleEvent(EventType type, void* data) {
char *cp = (char*)data;
printf("Handler: %s \n", cp);
}
};
int main(int argc, const char* argv[]) {
Handler handle;
Event event;
char c[] = "what?";
event.registerForEvent(TEST_TYPE_A, &handle);
event.sendEvent(TEST_TYPE_A, (void*)c);
return 0;
}
Thanks in advance for any pointers! I'm kinda stuck on this.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
让我们应用模板:
Let's apply templates:
这可以通过模板来完成,但需要大量的返工。首先根据要存储的数据类型对
EventHandler
进行模板化,并创建一些通用的EventHandlerBase
基类。对于注册和发送事件进行类型检查,您必须删除枚举并移动到某种类型的事件 ID,因此您可以调用registerForEvent
registerForEvent< TEST_TYPE_A >( &handle )
和sendEvent< TEST_TYPE_A >(whatever_type_this_is)
。您可以将测试类型定义为具有数据类型的嵌套 typedef 声明的结构。但是这样您就错过了在运行时区分事件类型的能力。您需要为每个事件类型生成一些唯一值,例如
typeid
的结果。This can be done with templates, but it would need quite a rework. Start by templating
EventHandler
by the kind of data to store, and create some common baseEventHandlerBase
class. For register and send event to do type checks you'll have to drop the enums and move to some typed kind of event id, so you can callregisterForEvent< TEST_TYPE_A >( &handle )
andsendEvent< TEST_TYPE_A >( whatever_type_this_is )
.You could have test types be defined as structs with a nested typedef declaration for the type of data. But then you have missed the ability to distinguish between event types at run-time. You will need to generate some unique value for each event-type type, like the result of
typeid
.基本上,要从
EventHandler
中删除void*
,您必须模板化EventHandler
,从而模板化Event
。这听起来很不高兴,直到您意识到每个EventType
应该接收相同的参数类型,对吗?如果没有,那么您可能还有其他问题。因此,您将为MouseEvent
提供一个Event
类,为KeyboardEvent
提供一个Event
类,无论如何,这是有意义的,因为它们来自不同的来源。唯一的问题是,现在您无法拥有一个接收或查看所有事件的函数,除非它也是模板化的。Basically, to remove
void*
fromEventHandler
, you'll have to templateEventHandler
, and thusEvent
. This sounds unhappy, until you realize that eachEventType
should be receiving the same parameter type, right? If not, then you probably have other problems. So you'll have oneEvent
class forMouseEvent
s and oneEvent
forKeyboardEvent
s, which makes sense anyway, since they come from different sources. The only problem is now you can't have a single function that receives or peeks at all events, unless it's also templated.