我如何用在这个回调中具有编译时类型检查的东西替换void指针?
How can I replace the void pointer with something that has compile time type checks in this callback?
我试图通过回调创建一个带有通知的事件系统。我写的代码,但它是依赖于空指针的工作。在我的上一个项目中,我想用编译时类型检查取代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;
}
提前感谢任何指示!我有点卡住了
让我们应用模板:
enum EventType {
TEST_TYPE_A,
TEST_TYPE_B
};
template <EventType> class EventData {};
template <> class EventData<TEST_TYPE_A> { /*****/ };
template <> class EventData<TEST_TYPE_B> { /*****/ };
// used by event receivers
class EventHandlerBase { public: virtual ~EventHandlerBase() { } };
template <EventType ET> class EventHandler : public EventHandlerBase
{
public:
virtual void handleEvent(EventData<ET> const& data) = 0;
};
class EventDispatcherBase { // Shared logic
protected:
std::set<std::shared_ptr<EventHandlerBase>> handlers;
void addHandler(std::shared_ptr<EventHandlerBase>);
void removeHandler(EventHandlerBase&);
};
typename <EventType ET> class EventDispatcher : private EventDispatcherBase {
public:
using EventDispatcherBase::addHandler;
using EventDispatcherBase::removeHandler;
void dispatchEvent(EventData<ET>& data) {
for (std::shared_ptr<EventHandlerBase> ptr : handlers) {
dynamic_cast<EventHandler<ET>&>(*ptr).handleEvent(data);
}
}
};
这可以用模板完成,但需要大量的返工。首先根据要存储的数据类型对EventHandler
进行模板化,并创建一些通用的基础EventHandlerBase
类。对于注册和发送事件进行类型检查,您必须放弃枚举并移动到某些类型的事件id,因此您可以调用registerForEvent< TEST_TYPE_A >( &handle )
和sendEvent< TEST_TYPE_A >( whatever_type_this_is )
。
您可以将测试类型定义为具有数据类型的嵌套类型定义声明的结构体。但是,这样就错过了在运行时区分事件类型的能力。您需要为每个事件类型类型生成一些惟一的值,就像typeid
的结果一样。
基本上,要从EventHandler
中删除void*
,您必须模板EventHandler
,因此Event
。这听起来令人不快,直到您意识到每个EventType
应该接收相同的参数类型,对吗?如果不是,那么你可能有其他问题。因此,您将为MouseEvent
s提供一个Event
类,为KeyboardEvent
s提供一个Event
类,这是有意义的,因为它们来自不同的来源。唯一的问题是现在你不能有一个函数接收或窥视所有事件,除非它也被模板化。
相关文章:
- 键入特征以检查类型是否可从流和 MSVC 读取
- 在编译时检查类型是否为 std::basic_string<T> C++
- 检查类型 T 是否具有成员函数 SFINAE 的任何重载
- 检查类型是否为模板的实例化
- 如何检查类型 'T' 是否具有'T(std::initializer_list<U>)'构造函数
- 使用 python 绑定来检查 C++ 类型是否是规范方式的指针、引用等?
- 检查类型的相等性
- C++编译时检查类型
- 使用模板C++检查类型
- 如何检查类型 T 是否在参数包 Ts 中
- 如何使用条件来检查类型名 T 是否是 C++ 中浮点类型的整数类型
- 检查类型是否在 C++ 中定义了 [][]
- 是否有类型特征检查类型之间的包含
- 如何在运行时检查类型
- 使用SFINAE检查类型是否可以绑定到模板模板参数
- 如何检查类型是否是给定类模板的实例化
- 如何在编译时检查类型
- 检查类型是否可以作为 boost::lexical_cast <string>的参数
- 如何检查类型是通过 typedef 定义的还是在模板参数中使用定义的
- 检查类型是否为地图