方法指针映射,编译器说他们不接受任何参数

map of method pointers, compiler says it they don't take any arguements

本文关键字:他们 不接受 任何 参数 编译器 指针 映射 方法      更新时间:2023-10-16

这个类要大得多,但我只发布有问题的代码。

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;

它编译和运行,当然,没有调用任何处理程序,但当调用带有两个参数的函数指针时,它怎么能在不带参数列表的情况下进行编译呢?有些事情很可疑,坦率地说,我不明白。你们这些聪明的人对此有什么见解吗?

您需要这样做:

(it->second)(wparam, lparam);  // note parens

无法删除这个问题,所以我想我会解释一下我是如何解决的。完全去掉了方法指针,在映射中使用了std::函数,然后在添加处理程序函数调用中使用std::bind。更容易使用系统指针和方法指针,更难一起存储在映射中。

试试这个代码:

(*this.*(it->second))(wparam , lparam)