2012-04-05 10 views
9

私は概念とエラーを理解しようとしています。これは何が問題なのですか?std :: function with non-static member functions

class A 
{ 
public: 
    A() 
    { 
     std::function<void(int)> testFunc(&A::func); 
    } 

private: 
    void func(int) {} 
} 

私の質問は、STD ::関数は奇抜な型定義なしを除いて、メンバ関数ポインタのように機能し、特定のインスタンスのメンバを呼び出すことができるであるオブジェクトの任意の並べ替えを作成することも可能であるということができますクラスを継承する際の関数パラメータとして使用することはできません。例えば:

class A 
{ 
public: 
    A() 
    { 
     index[WM_CREATE] = &A::close; 
     index[WM_DESTROY] = &A::destroy; 
    } 

protected: 
    map<UINT msg, void (A::*)(HWND, UINT , WPARAM, LPARAM)> index; 
    void close(HWND,UINT, WPARAM, LPARAM); 
    void destroy(HWND, UINT, WPARAM, LPARAM); 
}; 

class B : public A 
{ 
public: 
    B() 
    { 
     index[WM_CREATE] = &B::create; // error because it's not a pointer of type A::* 
    } 
private: 
    void create(HWND, UINT, WPARAM, LPARAM); 

}; 

私は私がSTDを使用しての正しい軌道に乗ってんだと思っています::そうのような機能:

class A 
{ 
public:    //   Gigantic stl error with these two 
    A()    //       | 
    {    //       V 
     index[WM_CREATE] = std::function<void(HWND, UINT, WPARAM, LPARAM>(&A::close); 
     index[WM_DESTROY] = std::function<void(HWND, UINT, WPARAM, LPARAM>(&A::destroy); 
    } 

protected: 
    map<UINT msg, std::function<void(HWND, UINT, WPARAM, LPARAM)> > index; 
    void close(HWND,UINT, WPARAM, LPARAM); 
    void destroy(HWND, UINT, WPARAM, LPARAM); 
}; 

class B : public A 
{ 
public:     //    and this one 
    B()     //      | 
    {      //      V 
     index[WM_CREATE] = std::function<void(HWND, UINT, WPARAM, LPARAM)>(&B::create); 
    } 
private: 
    void create(HWND, UINT, WPARAM, LPARAM); 

}; 

誰かがこれらの巨大な不可解なエラーが何を意味するかを説明し、どのようにすることができればそれらを修正する、私は非常にそれを感謝します。

+0

「std :: functionがメンバー関数ポインタのように動作する特定のインスタンスのメンバを呼び出す」と言うと、特定のインスタンスが 'std :: functionの作成時に指定されていることを意味します'オブジェクト?これは 'void(int)'シグネチャの示唆ですが、結果オブジェクトは "メンバ関数ポインタのように"動作しません。コールバック/ファンクタのように動作します。一方、結果として生成される 'std :: function'オブジェクトが実際にメンバー関数ポインタのように動作することを意味する場合、シグネチャは間違っています(代わりに、' void(A&、int) ')。どちらですか? –

+0

コールバック/ファンクタは何かわかりませんが、静的関数と非静的関数を区別しているように聞こえますが、静的でない関数にしたいと思っています。彼らはハンドラですので、このインスタンスメンバーだけを操作できる必要があります。例のように、対応するマップインデックスが渡されたときにその関数が呼び出されるようにしたいと思います。単純に、これを実行します。index [WM_CREATE](hwnd、msg、lparam、wparam);私はそれを行うために考えることができる唯一の方法は、ストアの関数ポインタまたは同様のものです。私は実際のポインタを行うことはできませんが、継承を破るので:( – FatalCatharsis

+0

['std :: mem_fun'] //en.cppreference.com/w/cpp/utility/functional/mem_fn)? –

答えて

11

私はあなたが持っている問題は、メンバ関数は、関数ポインタが、ポインタだけでなく、必要なことだと思いますオブジェクトを呼び出す。言い換えれば、メンバ関数には呼び出し元オブジェクトへのポインタである暗黙的な引数が追加されています。

std::function<void(int)> testFunc(std::bind(&A::func, this, _1)); 

これは、関数に現在のインスタンスのこのポインタを結合し、それが持っているので:

はSTD ::関数にメンバ関数を設定するには、次のようにのstd ::バインドを使用する必要があります関数ポインタとオブジェクトインスタンスは、関数を適切に呼び出すのに十分な情報です。 _1引き数は、関数が呼び出されたときに最初の明示的な引き数が提供されることを示します。

+0

エラーC2065: '_1':宣言されていない識別子。 'HandlerIndex [WM_CREATE] = std :: function (std :: bind(&BasicWindow :: MsgCreate、this、_1))' – FatalCatharsis

+0

のように呼びました。 'std :: function (std :: bind(&BasicWindow :: MsgCreate、this、_1、_2、_3、_4))' –

+0

ahちょっと家にいるときに試してみるよ。 – FatalCatharsis

0

私の質問は、この場合、実際には欠けている情報のみを特定のインスタンス

のメンバーを呼び出すことができるであるオブジェクトの任意の並べ替えを作成することも可能であるものを特定のインスタンスstd::functionオブジェクトを使用する必要があります。&A::funcは単独では使用できません(たとえば、(this->*&A::func)(0)&A::func、インスタンスは*this)。試してみてください:

std::function<void(int)> testFunc = std::bind(&A::func, this); 

std::bind(&A::func, *this)std::bind(&A::func, this)がわずかに異なる意味を持っていることに注意してください。)