2012-05-07 7 views
5

でコールバックとしてメンバ関数を指定します。 C++ 11は、(ClassBののコンストラクタで)であることをで行うための適切な方法になります。は、私は次のようしているC++ 11

ClassB::ClassB() 
{ 
    _obj.OnDoSomethingCool(
     [&](const std::string& arg) -> bool 
     { 
      return Juggle(arg); 
     }); 
} 

私が理解からは、コンパイラは、上記のラムダコードの外にはstd ::関数オブジェクトを作成します。コールバックが呼び出されると、std :: function :: operator()メンバーが呼び出され、ClassB :: Juggle()を直接呼び出す代わりにClassB :: Juggle()が呼び出されます。カバーの下で何が起こるのか間違っていない限り、すべてが少し非効率なようです。より良い方法がありますか?

+2

ラムダで(この例のように)キャプチャしてもVisual Studio 2010ではうまく動作しないことに注意してください。 –

答えて

6

実際にポリモーフィック関数が必要な場合は、std::functionのみを使用してください。それ以外の場合はテンプレートにします。

メンバ関数をファンクタに適合させるには、std::mem_fnを使用し、次にbindを使用して最初の引数にオブジェクトを追加すると、結果のファンクタがコールバックとして機能します。

サンプル:

#include <string> 
#include <functional> 

template<typename F> 
class ClassA 
{ 
public: 
    ClassA(F f) : _cb(f) {} 

private: 
    F _cb; 
}; 

class ClassB 
{ 
public: 
    ClassB() 
    : _obj(std::bind(&ClassB::Juggle, this, 
        std::placeholders::_1)) 
    {} 
    bool Juggle(const std::string& arg) {return true;} 
private: 
    ClassA<decltype(std::bind(
         std::declval<bool (ClassB::*)(const std::string&)>() 
         , std::declval<ClassB*>() 
         , std::placeholders::_1 
        )) > _obj; 
}; 

int main() 
{ 
    ClassB b; 
    return 0; 
} 

このサイド手順恐ろしく醜いことのコストで機能のコストを。

+0

bind()構文は、常に_1、_2、_3などのプレースホルダパラメータとは何か。私は今、C++にはlambdaがあると分かりましたが、bind()は時代遅れでした。しかし、bind()はBoostの外にあり、標準の一部になっているので、おそらく私はその仮定と間違っていたでしょう。 –

+2

@ArcadioAlivioSincero 'bind'は依然として有効です。時にはそれも短いです。私は、少しトリッキーな例をside-stepの 'function'に更新しました。 – pmr

+1

コールバックは柔軟性のために 'std :: function <>'を使用するのに適しています(コールバックの型*を登録するために*関数*を使用できることを考慮すると、それを格納するために何かユニフォームが必要です) –

関連する問題