2

Java のインターフェイス セマンティクスのようなものを C++ で使用できるようにしたかったのです。最初はboost::signal、特定のイベントに対して明示的に登録されたメンバー関数をコールバックしていました。これは本当にうまくいきました。

しかし、関数コールバックのいくつかのプールが関連していると判断し、それらを抽象化し、インスタンスの関連するすべてのコールバックを一度に登録することにしました。しかし、私が学んだことは、の特定の性質boost::bindおよび/または値を取ることが、thisそのブレークを作るように見えるということでした. あるいは、メソッド宣言によって生成さadd_listener(X &x)れるコードが変更されたという事実だけだったのかもしれません。boost::bind

問題が発生した理由は非常に大まかに理解しており、おそらく設計どおりに正しく機能していると思います。私は興味があります:代わりに何をすべきでしたか? 確かにそれを行う正しい方法があります。

コード例を次に示します。

#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <iostream>

using namespace std;

struct X;
struct Callback
{
    virtual void add_listener(X &x) = 0;
};

struct X
{
    X() {}
    X(Callback &c) {  c.add_listener(*this); }
    virtual void go() { cout << "\t'" << __PRETTY_FUNCTION__ << "'" << endl; }
};

struct CallbackReal : public Callback
{
    virtual void add_listener(X &x)
    {
        f = boost::bind<void>(boost::mem_fn(&X::go), x);
    }

    void go() { f(); }

    boost::function<void (void)> f;
};


struct Y : public X
{
    Y() {}

    Y(Callback &c) {  c.add_listener(*this); }
    virtual void go() { cout << "\t'" << __PRETTY_FUNCTION__ << "'" << endl; }
};


int main(void)
{
    CallbackReal c_x;
    CallbackReal c_y;

    X x(c_x);
    Y y(c_y);

    cout << "Should be 'X'" << endl;
    boost::bind<void>(boost::mem_fn(&X::go), x)();

    cout << "Should be 'Y'" << endl;
    boost::bind<void>(boost::mem_fn(&X::go), y)();

    cout << "------------------" << endl;

    cout << "Should be 'X'" << endl;
    c_x.go();
    cout << "I wish it were 'Y'" << endl;
    c_y.go();

    return 0;
}

さて、私は問題を完全に説明しませんでした。タイトルは誤解を招くものです。

ちょっと、あなた。これに反対票を投じてください。私は明らかに問題を十分に説明しておらず、最終的にはほとんどが構文エラーに帰着すると思います。:(

4

2 に答える 2

3

boost::bindパラメータを値で受け取り、それらをコピーします。つまり

f = boost::bind<void>(boost::mem_fn(&X::go), x);

は のコピーを渡し、xそのY一部を切り取ります (そもそも が本当に だった場合Y)。仮想ディスパッチを機能させるには、へのポインターを渡す必要がありますboost::bind

f = boost::bind(&X::go, &x);

(実際には を必要としないmem_fn、または を明示的に記述する必要がないことに注意してください。これは<void>boost::bindと 引数の演繹がそれらを処理してくれるためです。)

于 2010-10-27T22:51:28.090 に答える
0

Java インターフェースは、C++ 内には特に存在しません。あなたが得ることができる最も近いものは、純粋な抽象基本クラスです。これは一般的に十分に近いです。

あなたの質問の残りの部分は、インターフェースとは関係ありません。Java は、イベントの接続とディスパッチに Observer パターンを使用します。オブザーバーは特定のインターフェースに従う必要があるため、インターフェース部分はわずかに関連しています (もちろん、そうでなければ、何を呼び出すかわかりません)。

boost::bind を使用してファンクターを作成することは、実際にはインターフェイスを超えた抽象化であるため、より一般的なソリューションです。オブザーバー パターンとファンクターは、boost::signals、boost::signals2、gtk++ などのさまざまなライブラリに実装されているシグナル/スロット イディオム/パターンにまとめられています。Qt バージョンは、メカニズムはかなり異なりますが、コンセプトは似ています。

では、これは、何を、なぜ、どこで理解するのに役立つのでしょうか? Observer パターンとは何かを調べることから始めて、実装をいくつか書いてみることをお勧めします。

于 2010-10-27T23:24:31.197 に答える