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 のみを参照するようにします。

Pointer-to-member-function には、関連付けられたインスタンスがありません。インスタンスを呼び出すときに、ポインタをインスタンスにバインドします。したがって、マップは同じように簡単に静的メンバーにすることができます。

ポインターからこの関数を呼び出す方法。

構文は、 または のいずれか(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 に答える