我在CRTP模板中使用成员指针时遇到了一些问题。 这里的代码是一个虚拟调用函数,它调用crtp派生类的成员函数指针。
class KeyboardHandler {
public:
virtual void keyPressed(KeyboardKey) = 0;
virtual void keyReleased(KeyboardKey) = 0;
KeyboardHandler & operator=(const KeyboardHandler &) = default ;
};
template<class T>
class KeyboardHandlerOpti : public KeyboardHandler {
public:
using KeyboardCallback = void (T::*)(KeyboardKey key, KeyboardStatus status) ;
KeyboardHandlerOpti(KeyboardCallback defaultCallback);
virtual void keyPressed(KeyboardKey key) override final;
virtual void keyReleased(KeyboardKey key) override final ;
std::vector<KeyboardCallback> mCallbackPressed ;
std::vector<KeyboardCallback> mCallbackReleased ;
KeyboardHandlerOpti & operator=(const KeyboardHandlerOpti &) = default ;
private:
KeyboardCallback mDefaultCallback ;
};
class GlfwDefaultKeyboardHandler :
public KeyboardHandlerOpti<GlfwDefaultKeyboardHandler> {
public:
GlfwDefaultKeyboardHandler() ;
GlfwDefaultKeyboardHandler & operator=(const GlfwDefaultKeyboardHandler &) = default ;
private:
//This is type of KeyboardCallback
void drawKey(KeyboardKey key, KeyboardStatus status) ;
} ;
使用drawKey将类GlfwDefaultKeyboardHandler初始化为KeyboardHandlerOpti :: mDefaultCallback
template<class T>
KeyboardHandlerOpti<T>::KeyboardHandlerOpti(KeyboardCallback defaultCallback) :
mDefaultCallback(defaultCallback),
mCallbackPressed(getKeyboardKeyCount(), mDefaultCallback),
mCallbackReleased(getKeyboardKeyCount(), mDefaultCallback) {
}
和Callback被调用
template<class T>
void KeyboardHandlerOpti<T>::keyPressed(KeyboardKey key) {
KeyboardCallback c = mCallbackPressed[getKeyValue(key)] ;
(dynamic_cast<T *>(this)->*c)(key, KeyboardStatus::ePressed) ;
//(this->*c)(key, KeyboardStatus::ePressed) ;
}
不幸的是我有一个段错误,我无法理解为什么。我在调试中发现了一些有趣的价值。我可以看到在KeyboardHandlerOpti的构造中,我有一些我不太懂的东西。
defaultCallback值为0x4b7578,debuger可以告诉函数的名称,但mDefaultCallback是“0x7ef360,此调整为96”,两个向量中的值相同。
所以如果有人能向我解释为什么我会遇到段错误,我会非常高兴。
答案 0 :(得分:4)
Memebers按照它们在类定义中列出的顺序进行初始化,不按照它们出现在构造函数的初始化列表中的顺序进行初始化。在KeyboardHandlerOpti
构造函数中,mCallbackPressed
和mCallbackReleased
首先被初始化,然后才为mDefaultCallback
分配一个值。所以你把你的载体装满了随机的垃圾。在形式上,您的程序表现出不确定的行为。
成功
template<class T>
KeyboardHandlerOpti<T>::KeyboardHandlerOpti(KeyboardCallback defaultCallback) :
mCallbackPressed(getKeyboardKeyCount(), defaultCallback),
mCallbackReleased(getKeyboardKeyCount(), defaultCallback),
mDefaultCallback(defaultCallback)
{
}
即,使用defaultCallback
填充向量。将mDefaultCallback
移到最后并不是技术上必需的,它只是使列表中的顺序与初始化程序实际执行的顺序相匹配(我相信一些编译器会在初始化程序处于“错误”顺序时发出警告)。