这个类要大得多,但我只会发布有问题的代码。
template<class T>
class BaseWindow : public IWindow
{
typedef void(T::*HandlerPtr)(WPARAM, LPARAM)
public:
LRESULT CALLBACK BaseWindow<T>::WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
// various stuff
private:
void AddHandler(long id, HandlerPtr func);
private:
std::map<long, void(T::*)(WPARAM, LPARAM)> m_MessageHandlers;
}
template<class T>
void BaseWindow<T>::AddHandler(long id, HandlerPtr func)
{
m_MessageHandler.insert(std::pair<long, HandlerPtr>(id, func));
}
template<class T>
LRESULT CALLBACK Dapper32::BaseWindow<T>::WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
if(m_MessageHandlers.count(msg) == 1)
{
auto it = m_MessageHandlers.find(msg);
it->second(wparam, lparam); // <-- error here for all template instantiations
return 0;
}
return DefWindowProc(hwnd, msg, wparam, lparam);
}
这是一个小背景。为了娱乐和练习,我正在制作一个win32包装器,因为它看起来像一个有趣,冗长的项目需要解决。经过一番考虑后,我决定我更喜欢在地图中存储消息处理程序的系统,而不是每条消息都有自己的虚函数,甚至更糟糕的是,使用巨大的switch语句。这里的目标是,您从此BaseWindow类派生,然后模板参数是派生类。像
这样的东西class MyWindow : public BaseWindow<MyWindow>
然后你创建将处理特定消息的私有方法,然后调用传入消息id的AddHandler函数,然后调用指向该方法的指针。像蛋糕一样简单,我已经确认它们已正确输入地图。但是,在BaseWindow类中,我收到错误:
error C2064: term does not evaluate to a function taking 2 arguments
我觉得这很奇怪,因为每个地方都绕过指针,声明肯定会带两个参数。当我删除括号和争论使它看起来像:
it->second;
它编译并运行,当然,没有一个处理程序被调用,但是如果调用带有两个参数的函数指针而不采用争论列表,它怎么能编译?有些东西是可疑的,坦白说我不懂。你们这些聪明的人有没有对此有任何见解?
答案 0 :(得分:4)
你需要这样做:
(it->second)(wparam, lparam); // note parens
答案 1 :(得分:1)
无法删除问题所以我想我会解释我是如何解决它的。完全摆脱了方法指针,在map中使用了std :: functions,然后在add handler函数调用中使用了std :: bind。更容易使用系统和方法指针更难以一起存储在地图中。
答案 2 :(得分:0)
试试这段代码:
(*this.*(it->second))(wparam , lparam)