0

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

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;

它编译并运行,当然,没有调用任何处理程序,但是当调用具有两个参数的函数指针而不使用争论列表时,它怎么能编译呢?有些东西很可疑,坦率地说我不明白。你们有没有聪明的头脑对此有任何见解?

4

3 回答 3

4

你需要这样做:

(it->second)(wparam, lparam);  // note parens
于 2012-11-16T17:51:26.610 回答
1

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

于 2012-12-16T23:10:46.747 回答
0

试试这个代码:

(*this.*(it->second))(wparam , lparam)
于 2013-01-01T14:02:35.350 回答