3

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

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;
}

我的问题是,这是将指向成员函数的指针添加到对象内的映射的正确方法,以便您仅引用单个实例的func1or func2

而且,我不知道如何从指针调用这个函数。会是这样吗?

map["func1"](2,4);

使用成员函数时,我对语法有点困惑。

4

3 回答 3

7

首先,代码:

#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);
}

现在,对于您的问题:

我的问题是,这是将成员函数的指针添加到对象内的映射的正确方法吗

我发现下标运算符[]比您所做的插入更容易阅读。

以便您仅引用单个实例的 func1 或 func2。

指向成员函数的指针没有与之关联的实例。当您调用它时,您将指针绑定到一个实例。因此,您的地图也可以很容易地成为静态成员。

我将如何从指针调用这个函数。

语法是:(instance.*pointer)(args)(class_pointer->*pointer)(args)。由于您没有说明应该在哪个实例上调用函数,我假设this. 您的指针位于地图中,因此我们有:

((this)->*(this->pointerMap["func1"]))(arg1, arg2)

或者

(this->*pointerMap[name])(x, y);
于 2012-04-04T21:47:46.813 回答
2

这有点对。也许 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);

实际上,这两种地图访问都不是一个好主意,因为您绝对必须检查地图项是否存在,否则您的指针会出错。所以我推荐这样的东西:

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); }
}
于 2012-04-04T21:49:45.290 回答
1

这是将指针插入映射的正确方法,但您可以使用 来整理一下make_pair,它会为您推导出模板参数:

pointerMap.insert(std::make_pair("func1", &func1));  // The '&' is optional

要调用函数,您需要使用.*or->*运算符,具体取决于您调用它的对象是否通过指针引用:

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);
于 2012-04-04T21:48:51.247 回答