我正在构建一个简单的侦听器/回调机制,用于我当前的实验项目。而我坚持实现一个容器结构似乎应该是指针向量的向量。我选择这种方式是因为我希望根向量简单具有事件类型的键,假设是枚举(int),然后在此键我想存储指向此事件类型的可用方法的指针的向量。在逻辑表示中类似于:
[EVENT_TYPE_QUIT]
[ptr1]
[ptr2]
[ptr3]
[ptr4]
[....]
[EVENT_TYPE_HELLO]
[....]
[....]
typedef enum {
EVENT_TYPE_QUIT,
EVENT_TYPE_HELLO,
...
} EventType;
因此,简化的实现看起来像这样(它是现实中的模板,但想象T是可以映射事件的任何用户类型)。
class EventMapper {
...
typedef void (T::*functionPtr)(); // simple pointer to T member function with no args.
std::vector< std::vector<functionPtr> > eventCallbacks;
void mapEvent(const EventType type, functionPtr callback) {
// here i need to map type to callback
// each type can have multiple callbacks
// T can have only distinct event types as "key"
// this i tried but doesn't work
eventCallbacks[type].push_back(callback);
}
...
}
预期的实现类似于:
EventMapper<SupaDupaClass> mapper;
mapper.mapEvent(EVENT_TYPE_HELLO, &SupaDupaClass::didYouSayHello);
等等......
我真的想用vector而不是map来更简单的键分配吗? 谢谢
答案 0 :(得分:1)
如果我正确地读了你的代码,你正在访问未初始化的条目。
首先应使用空向量初始化eventCallbacks,例如
eventCallbacks.assign(10,标准::矢量())
答案 1 :(得分:1)
您可以使用std::map
将event_type映射到回调矢量。并考虑使用std::function
而不是函数指针来实现灵活性。
一种可能的实现方式是:
#include <vector>
#include <map>
#include <functional>
#include <iostream>
enum class event_type
{
event_one,
event_two
};
void func1() { std::cout << "func1" << std::endl; }
class my_listener { public: void func() { std::cout << "my_listener::func" << std::endl; } };
int main()
{
std::map<event_type, std::vector<std::function<void ()>>> m;
my_listener lst;
m[event_type::event_one].push_back(std::bind(&my_listener::func, lst));
m[event_type::event_one].push_back(&func1);
// invoke callbacks (may be used in the code that raises events)
for(auto& kv : m)
{
for(auto& f : kv.second) {
f();
}
}
return 0;
}
修改强> 您可以考虑使用Boost.Signals2库。