派生 class 上的成员函数指针
Member function pointer on derived class
我在使用 CRTP 模板中的成员指针时遇到一些问题。
这里的代码是一个虚调用函数,调用一个crtp派生的成员函数指针class.
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) ;
} ;
class GlfwDefaultKeyboardHandler 使用 drawKey 初始化为 KeyboardHandlerOpti::mDefaultCallback
template<class T>
KeyboardHandlerOpti<T>::KeyboardHandlerOpti(KeyboardCallback defaultCallback) :
mDefaultCallback(defaultCallback),
mCallbackPressed(getKeyboardKeyCount(), mDefaultCallback),
mCallbackReleased(getKeyboardKeyCount(), mDefaultCallback) {
}
和回调被调用
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,调试器可以知道函数的名称,但是 mDefaultCallback 是“0x7ef360,这个调整 96”,它在两个向量中是相同的值。
所以如果有人能向我解释为什么我有段错误我会很高兴。
成员按照它们在 class 定义中列出的顺序进行初始化,而不是 按照它们在构造函数的初始化列表中出现的顺序进行初始化。在KeyboardHandlerOpti
构造函数中,mCallbackPressed
和mCallbackReleased
先被初始化,然后才给mDefaultCallback
赋值。所以你把你的向量塞满了随机垃圾。正式地,您的程序表现出未定义的行为。
成功
template<class T>
KeyboardHandlerOpti<T>::KeyboardHandlerOpti(KeyboardCallback defaultCallback) :
mCallbackPressed(getKeyboardKeyCount(), defaultCallback),
mCallbackReleased(getKeyboardKeyCount(), defaultCallback),
mDefaultCallback(defaultCallback)
{
}
也就是说,使用 defaultCallback
来填充向量。将 mDefaultCallback
移动到末尾在技术上不是必需的,它只是使列表中的顺序与实际执行初始化程序的顺序相匹配(我相信一些编译器会在初始化程序处于 "wrong" 顺序时发出警告)。
我在使用 CRTP 模板中的成员指针时遇到一些问题。 这里的代码是一个虚调用函数,调用一个crtp派生的成员函数指针class.
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) ;
} ;
class GlfwDefaultKeyboardHandler 使用 drawKey 初始化为 KeyboardHandlerOpti::mDefaultCallback
template<class T>
KeyboardHandlerOpti<T>::KeyboardHandlerOpti(KeyboardCallback defaultCallback) :
mDefaultCallback(defaultCallback),
mCallbackPressed(getKeyboardKeyCount(), mDefaultCallback),
mCallbackReleased(getKeyboardKeyCount(), mDefaultCallback) {
}
和回调被调用
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,调试器可以知道函数的名称,但是 mDefaultCallback 是“0x7ef360,这个调整 96”,它在两个向量中是相同的值。
所以如果有人能向我解释为什么我有段错误我会很高兴。
成员按照它们在 class 定义中列出的顺序进行初始化,而不是 按照它们在构造函数的初始化列表中出现的顺序进行初始化。在KeyboardHandlerOpti
构造函数中,mCallbackPressed
和mCallbackReleased
先被初始化,然后才给mDefaultCallback
赋值。所以你把你的向量塞满了随机垃圾。正式地,您的程序表现出未定义的行为。
成功
template<class T>
KeyboardHandlerOpti<T>::KeyboardHandlerOpti(KeyboardCallback defaultCallback) :
mCallbackPressed(getKeyboardKeyCount(), defaultCallback),
mCallbackReleased(getKeyboardKeyCount(), defaultCallback),
mDefaultCallback(defaultCallback)
{
}
也就是说,使用 defaultCallback
来填充向量。将 mDefaultCallback
移动到末尾在技术上不是必需的,它只是使列表中的顺序与实际执行初始化程序的顺序相匹配(我相信一些编译器会在初始化程序处于 "wrong" 顺序时发出警告)。