【发布时间】:2013-05-26 19:47:59
【问题描述】:
我正在尝试构建一个类来处理键回调。
为此,我有一个这样定义的地图:
class Keyboard {
public:
void registerCallback(int key, callback_fn func, bool repeat = false);
void onKeyEvent(int key, int state);
private:
typedef std::function<void (int)> callback_fn;
struct Callback {
Callback(callback_fn f, bool r)
: func(f), repeat(r), last_state(-1) {}
callback_fn func;
bool repeat;
int last_state;
};
std::unordered_map<int, std::vector<Callback>> callbacks;
};
然后我像这样注册回调:
void Keyboard::registerCallback(int key, callback_fn func, bool repeat) {
// My understanding is that if there is nothing mapped to the key
// it will create a new vector. Otherwise it will return the mapped
// object. I did try checking if anything already exists at the key
// and if not creating a new vector but it yielded the same results.
callbacks[key].push_back({ func, repeat });
}
但是我遇到了一个问题,即映射矢量似乎丢失了它的所有元素。
当我注册回调时,给定键处的向量会增加大小,但是当我尝试用另一种方法迭代向量时,它没有元素。
下面是我对向量进行迭代的方法。
void Keyboard::onKeyEvent(int key, int state) {
for(auto& callback : callbacks[key]) {
if(callback.repeat || callback.last_state != state) {
callback.func(state);
}
}
}
请注意,如果我将std::cout << callbacks[key].size() << std::endl; 添加到它会打印0 的函数顶部。
如果重要,这里是我如何注册回调的示例。
keyboard.registerCallback('w', [](int state) {
std::cout << "w " << (state == GLFW_PRESS ? "pressed" : "released") << std::endl;
}, true);
我怀疑我的问题源于我更习惯的 Java 映射和 C++ 映射之间的差异
【问题讨论】:
-
在 registerCallback 调用之后会打印什么:
std::cout << keyboard.callbacks['w'].size();? -
当您检索回调向量时,您确定使用与添加它们时相同的
callbacks实例吗? -
只有这些被调用的函数会修改
callbacks吗?你确定你没有在某处创建和操作callbacks的副本吗? -
callbacks只有一个实例,它都保存在一个 Singleton 类中,Keyboard并且这些是唯一可以访问callbacks的函数 抱歉,上面没有说清楚,我已更新以尝试反映这一点。 -
或者它是一个不同的密钥,或者它还没有注册。我建议如下:将
std::cout << "Registering " << key << std::endl;放在registerCallback()的开头,将std::cout << "Looking up for " << key << std::endl;放在onKeyEvent的开头。您是否以正确的顺序和相同的数字键值看到输出? (为了 100% 确定我会在Keyboard对象的构造函数中添加一个cout。)