C++ 插入到成员函数指针的映射中

C++ 插入到成员函数指针的映射中,c++,C++,我的问题有点复杂,所以我将从一个例子开始: class a { public: a() { pointerMap.insert(pair<std::string, void a::*(int, int)> ("func1", func1); pointerMap.insert(pair<std::string, void a::*(int, int)> ("func2", func2); } priv

我的问题有点复杂,所以我将从一个例子开始:

class a
{
public:
     a()
     {
          pointerMap.insert(pair<std::string, void a::*(int, int)> ("func1", func1);
          pointerMap.insert(pair<std::string, void a::*(int, int)> ("func2", func2);
     }

private:
     void func1(int a, int b);
     void func2(int a, int b);
     std::map<std::string, void a::* (int, int)> pointerMap;
}
使用成员函数时,我对语法有点困惑。

首先,代码:

#include <map>
#include <string>
class a
{
public:
     a()
     {
       pointerMap["func1"] = &a::func1;
       pointerMap["func2"] = &a::func2;
     }

     void invoke(const std::string& name, int x, int y) {
       if(pointerMap[name])
         (this->*pointerMap[name])(x, y);
     }

private:
     void func1(int a, int b) {};
     void func2(int a, int b) {};
     std::map<std::string, void (a::*)(int, int)> pointerMap;
};

int main () {
  a o;
  o.invoke("func1", 1, 2);
}


这是将指针插入映射的正确方法,但您可以使用
make\u pair
稍微整理一下,它可以为您推导模板参数:

pointerMap.insert(std::make_pair("func1", &func1));  // The '&' is optional
要调用函数,需要使用
*
->*
运算符,具体取决于调用函数的对象是否通过指针引用:

a obj;  // Regular object
(a .* map["func1")(2, 4);  // Extra parens needed due to operator precedence

a *ptr;  // Pointer
(a ->* map["func1")(2, 4);
有些人喜欢定义宏以使其更清楚地显示您正在执行的操作,因为语法对某些人来说可能有点混乱:

#define CALL_MEMBER_FUN_PTR(obj, fun) ((obj) ->* (fun))
...
a *ptr;
CALL_MEMBER_FUN_PTR(ptr, map["func1"])(2, 4);

有点对。也许typedef可以让事情变得更干净:

typedef std::map<std::string, void(a::*)(int, int)> pfmap_type;
pfmap_type m;               //    ^^^^^^

// ...

m.insert(pfmap_type::value_type("hello", &a::func1));
                                      // ^^^

(this->*(m["hello"]))(1, 2);
(this->*(m.find("hello")->second))(3, 4);

你能介绍一下背景吗?这样设置类的目的是什么?使用
std::make_pair(“func1”,func1)
,它将为您推断类型。这只是我涂鸦的一个小示例,旨在将问题简化为概念。实际上,我正在尝试制作自己的小win32包装器,它是面向对象的。这是为了安装消息处理程序,其中索引是msg(我知道它实际上是一个uint,只是使用了一个字符串作为示例),存储的是指向您编写的函数处理程序的成员函数指针。当收到消息时,它会查看映射中是否存储了相同类型的消息,并调用其处理程序。你永远不会在实例之外访问这些。哇,这是非常彻底的好先生。我不知道在没有插入索引的情况下使用下标操作符不会导致越界错误。因此,对不存在的索引使用下标运算符将在映射中为您创建一个索引?@FatalCatharsis:是的,它将创建一个默认的初始化值。(在本例中为空指针)是的,这很酷。所以现在我需要做的就是在访问它之前验证一个具有该名称的映射索引是否存在,并偶然检查一个空函数指针,然后我就设置好了。感谢您回答我的问题以及更多:P@FatalCatharsis-我为您的
invoke()
方法添加了
if
。使用just it可以完成你要求的两件事。
a obj;  // Regular object
(a .* map["func1")(2, 4);  // Extra parens needed due to operator precedence

a *ptr;  // Pointer
(a ->* map["func1")(2, 4);
#define CALL_MEMBER_FUN_PTR(obj, fun) ((obj) ->* (fun))
...
a *ptr;
CALL_MEMBER_FUN_PTR(ptr, map["func1"])(2, 4);
typedef std::map<std::string, void(a::*)(int, int)> pfmap_type;
pfmap_type m;               //    ^^^^^^

// ...

m.insert(pfmap_type::value_type("hello", &a::func1));
                                      // ^^^

(this->*(m["hello"]))(1, 2);
(this->*(m.find("hello")->second))(3, 4);
void call(const char * key, int a, int b) const
{
    pfmap_type::const_iterator it = m.find(key);
    if (it != m.end()) { (this->*(it->second))(a, b); }
}