2016-05-02 16 views
0

私のC++は錆びています。私はMyClassにFooについて何も知らず、fooで関数を実行するためのコールバックを持っていたいと思います。私はcallback_pairまたはどのようにまあ、MyClassFoo、あなたがコールバックとして使用する予定のどんな方法のつまり署名何かを知らなければならないのsetCallback不明なクラス+関数をコールバック

class MyClass{ 
    tuple<cb, ptr> callback_pair 

    int run() { 
     auto that=callback_pair<1>(); 
     auto cb = callback_pair<0>(); 
     int a=1, b=2, c=3; 
     auto result = cb(that, a, b, c); //this calls foo.the_function 
     return result; 
    } 
    void SetCallback(tuple<cb, ptr> cb) { callback_pair=cb;) 
}; 

class Foo { 
    int d; 
    int the_func(int a, b, c) { 
     return a+b+c+d 
    } 
} 
//myclass.SetCallback(what_do_I_write_here) 
+0

仮想クラスを作成して回避策を作成しました。 MyClassはそれについて知っています、Fooはそれを実装しています。しかし私は私が尋ねたものに近い答えをしたいと思います –

+0

私たちは 'std :: function'と' std :: bind'を持っています。 –

答えて

1

を呼び出すことを定義する方法がわかりません。さもなければ、どのようにパラメータとして渡すべきか、あるいはどのような型を出力として受け取るべきかを知ることができますか?コールバック署名が知られており、固定されている場合は、上記の持っているように、例えばint(int,int,int)のために、あなたはこのような工事を使用することができます。

class MyClass { 
    std::function<int(int,int,int)> callback; 

public: 
    int run() { 
     return callback(1,2,3); // or whatever 
    } 

    template <typename Class> 
    void SetCallback (Class& o, int (Class::*m) (int,int,int)) { 
     callback = [&o,m] (int a, int b, int c) { return (o.*m)(a,b,c); }; 
    } 

    template <typename Class> 
    void SetCallback (Class const& o, int (Class::*m) (int,int,int) const) { 
     callback = [&o,m] (int a, int b, int c) { return (o.*m)(a,b,c); }; 
    } 
}; 

MyClass作品の上記の実装は次のよう:callbackは当初、未定義の関数オブジェクトです、 3つのintがあり、intを返します。 SetCallbackは、コールバックを実行するオブジェクトoと、callbackの署名に準拠するオブジェクトのメソッドmの2つのパラメータをとります。それはoのタイプが何であるか気にしません。タイプ消去のおかげで、MyClassは実際に何を呼んでいるのかを知る必要はありません。

constと非constについてそれぞれ1つずつ、SetCallbackの2つのバージョンに特に注意してください。実際には、volatileconst volatileのオーバーロードも記述する必要がありますが、それはconstよりもはるかに稀です。将来、例外仕様とトランザクションが型システムの一部になると、noexceptと同期についても注意する必要があります。その結果、タイプのコンビナトリアルな爆発は、非常に巧妙な言語サポートなしでは効果的に処理することが難しくなります。しかし、この例では、そのような種類のコードがどのように記述されるのかを示しています。

実装は醜いようですが、実際にはきれいなインターフェイスが提供されます。上記のコードは、署名int(int,int,int)と方法を持っている任意のタイプで動作します

MyClass test; 
Foo foo; 

foo.d = 4; 
test.SetCallback (foo, &Foo::the_func); 
int result = test.run(); // result = 10 

Foo与えられたあなたは上記の書いたように、あなたはこのようなMyClassのコールバック機能を使用します。 runに電話する前にSetCallbackに電話する必要があります。コールバックがまだ定義されていないため、std::bad_function_call例外が発生します。