2016-05-10 15 views
0

[1]にあるコールバックの例を少し変更して、次のようにして呼び出し元に登録を移動させました。lambdaを使用したC++コールバックがbad_function_callで失敗する

// To build: 
// g++ -std=c++11 callback4.cpp 

#include <stdio.h> 
#include <functional> 

//------------------------------------------------------------------------ 
// Callback function. 
typedef std::function<int(int)> CallbackFunction; 

//------------------------------------------------------------------------ 
// "Caller" allows a callback to be connected. It will call that callback. 
class Caller 
{ 
    public: 
    // Clients can connect their callback with this. 
    void connectCallback(CallbackFunction cb) 
    { 
     printf("setting the callback..\n"); 
     m_cb = cb; 
     // This call works 
     m_cb(10); 
    } 

    // Test the callback to make sure it works. 
    void test() 
    { 
     printf("Caller::test() calling callback...\n"); 
     int i = m_cb(10); 

     printf("Result (50): %d\n", i); 
    } 

private: 
    // The callback provided by the client via connectCallback(). 
    CallbackFunction m_cb; 
}; 

//------------------------------------------------------------------------ 
// "Callee" can provide a callback to Caller. 
class Callee 
{ 
    public: 
    Callee(Caller c, int i) : m_i(i), caller(c) { } 

    // The callback function that Caller will call. 
    int callbackFunction(int i) 
    { 
     printf(" Callee::callbackFunction() inside callback\n"); 
     return m_i * i; 
    } 

    void registerCallback() { 
     caller.connectCallback(
     [this](int i) { return this->callbackFunction(i); }); 
    } 

private: 
    // To prove "this" is indeed valid within callbackFunction(). 
    int m_i; 
    Caller caller; 
}; 

//------------------------------------------------------------------------ 

int main() 
{ 
    Caller caller; 
    Callee callee(caller, 5); 

    callee.registerCallback(); 

    // Test the callback. This fails. 
    caller.test(); 

    return 0; 
} 

ここでは、この参照でラムダ式で被告を捕捉しています。しかし、Caller内で呼び出すtest()の呼び出しは、実行時にbad_function_callをスローしません。しかし、登録時にコールバックを呼び出すことができます。それがどんなアイデアなのか?出力は以下の通りです。コールバック内部のコールバック..
呼び出し先:: callbackFunction()
発信者::テスト()を呼び出すコールバック...
を設定

'のstd :: bad_function_call'
のインスタンスを投げた後に呼び出さTERMINATE ()何 :bad_function_call

[1] http://tedfelix.com/software/c++-callbacks.html

+1

'caller'のコピーのコピーを変更しています。 –

答えて

3

がを見てみましょうコンストラクタ:ここ

Callee(Caller c, int i) : m_i(i), caller(c) { } 

は、あなたがあなたのオブジェクトをコピーを意味し、値によってCallerを渡します。

だからmain関数内で変数callerないCallee::callerと同じです。 main変数callerにはコールバックが登録されていません。

簡単な解決策は参照使用することです:

class Callee 
{ 
    public: 
    Callee(Caller& c, int i) : m_i(i), caller(c) { } 
    ... 

    private: 
    ... 
    Caller& caller; 
}; 

よりよい解決策は、設計を再考するかもしれない、と何の問題、あなたが実際に解決しようとすると、ユースケースについてされているが。

+0

私は参照してください。それはうまくいった。しかし、なぜあなたはこれがより良くなると思いますか?このアプローチで見られる問題はありますか? – chamibuddhika

+1

@chamibuddhikaほとんどの場合、参照を渡すことはできますが、参照を使用できる状況ではないので、スキーム全体が崩れてしまいます。しかし、実際にはこの解決策で解決しようとする問題は非常に多くのユースケースに左右されます。 –

+0

私は参照してください。明確化のためにありがとう。 – chamibuddhika

関連する問題