方法指针的映射,编译器说它们不带任何参数

时间:2012-11-16 17:47:00

标签: c++ visual-studio-2010 winapi

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

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;

它编译并运行,当然,没有一个处理程序被调用,但是如果调用带有两个参数的函数指针而不采用争论列表,它怎么能编译?有些东西是可疑的,坦白说我不懂。你们这些聪明的人有没有对此有任何见解?

3 个答案:

答案 0 :(得分:4)

你需要这样做:

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

答案 1 :(得分:1)

无法删除问题所以我想我会解释我是如何解决它的。完全摆脱了方法指针,在map中使用了std :: functions,然后在add handler函数调用中使用了std :: bind。更容易使用系统和方法指针更难以一起存储在地图中。

答案 2 :(得分:0)

试试这段代码:

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