2011-07-27 16 views
4

私は、特殊なデータ構造を持つクラスTestを持っています。マップの構造体内からPointer-to-Member-Functionによって指された関数を呼び出す

typedef struct { 
    void (Test::*f) (void) const; 
} pmf_t; 

初期化OKです:キーがstd::stringであり、マップされた値は次のように定義structあるクラスTeststd::map部材があります。問題は、私が指している関数を呼び出そうとしているときです。問題を再現したおもちゃの例を作った。ここでは、次のとおりです。事前に

#include <iostream> 
#include <map> 

using namespace std; 

class Test; 
typedef void (Test::*F) (void) const; 
typedef struct { 
    F f; 
} pmf_t; 


class Test 
{ 
public: 
    Test() { 
    pmf_t pmf = { 
     &Test::Func 
    }; 
    m["key"] = pmf; 
    } 
    void Func (void) const { 
    cout << "test" << endl; 
    } 
    void CallFunc (void) { 
    std::map<std::string, pmf_t>::iterator it = m.begin(); 
    ((*it).second.*f)(); // offending line 
    } 

    std::map<std::string, pmf_t> m; 
}; 


int main() 
{ 

    Test t; 
    t.CallFunc(); 

    return 0; 
} 

おかげで、 JIR

答えて

5

pmf_tタイプの名前はfであるため、最初に変更したのは、を削除してsecond.fになります。これにより、メンバーへのポインタ値が得られます。 を使用するには、インスタンスへのポインタが必要です。あなたは正しいタイプの利用可能な唯一のはとても->*オペレータとそれを使う、thisである:(

(this->*it->second.f)(); 

あなたは全部の周りに括弧を必要とする、または他のコンパイラはあなたがit->second.f()を呼び出すようにしようとしていると考えていますは許可されていません)、結果を->*に適用します。

(this->*((*it).second.f))(); 
+0

丁寧な説明、ありがとう。私はイテレータに 'this'を前置することを考えたことはありませんでした。 – Jir

+0

イテレータにプリフェッチしていません。あなたはそれをメンバーへのポインタ式の前に置いています。 ( ' - >'と '.'演算子は' - > * 'よりも緊密に束縛されます;完全なカッコで囲まれたバージョンがあります:'(this-> *((it-> second).f))() '。 –

1

私はあなたがこのいずれかにC++ FAQをチェックアウトするかもしれないと思います。シンタックスは明らかに難しいものです(マクロを使用することをお勧めします)。

+0

あなたは示唆しました。しかし、私はまだその関数を呼び出す方法を把握することはできません。とにかく入力していただきありがとうございます! – Jir

+1

*メンバーへのポインタを作成することは問題ではありませんでした。 –

+0

@Rob、whoops、1つのエントリをあまりに早くリンクしました。 OPは実際に* next * FAQを望んでいます。これはマクロを使って関数を呼び出すことを示唆しています。私はリンクを更新しました。 –

1

が、これは試してみてください。意図はthisオブジェクトのためにそれを呼び出すことであれば、私は、コールが

this->*は、現在のオブジェクトのポインタ・ツー・メンバーを逆参照するための構文です
( this->* ((*it).second.f))(); 

ようになるはずと信じています。 ((*it).second.f)はマップから取り出されたポインタであり、()は実際に関数を呼び出すための呼び出し演算子です。

これは練習としては良いかもしれませんが、それ以外の用途には適していません。

3

問題のある行がそれを呼び出すために任意のオブジェクトなしメンバ関数を呼び出すようにしようとしている:

1

それはこの質問のために遅すぎるかもしれないが、それはかなり明確に見えるので、一見複雑なsynataxは2つのシンプルなラインに打破することができます。私のように `typedef`を使用した例を編集した

void CallFunc (void) 
{ 
    pmf_t t = m["key"]; //1>get the data from key 
    (this->*t.f)();  //2>standard procedure to call pointer to member function 
} 
+0

、これは読みやすさに有利です。私はローカル変数 't'を作成することがパフォーマンスの脅威になるのではないかと思います。 – Jir

+0

私はこの余分なラインは一般的にパフォーマンスドラグがあまりにも多く、それでも読みやすさはかなり高くなっているとは思わない。この方法でプロジェクトをより良く管理することができますので、この機能が重要なパフォーマンスのボトルネックになっていると言わない限り、私はこの1つを個人的に好むでしょう... – Gob00st

関連する問題