0

クラス Manager とクラス Base があります (Base から派生したサブクラスを持ち、たとえば A : public Base)。Manager 内で Base の適切なサブクラスを作成しますが、Base は Manager の存在を認識しません。この作成された Base のサブクラスに、A オブジェクトが呼び出す Manager クラスのメンバー メソッドにバインドされた関数オブジェクトを渡したいと思いました。つまり、作成中は次のようになります。

void Manager::createThing()
{
FunctionObject func;
if (doExtraWork)
    func.bind(&Manager::someMethod, this);

Base *bla = new A(func);
}

次に、A の内部で、マネージャーに引き継がせる余分な作業があるかどうかを検出できるようにしたいと思います。たとえば、次のようになります。

A::update()
{
 if (func) //ideally detect if func was bound to someMethod or func is empty
    func(this); //equivalent to the above instance of manager calling someMethod on this instance of A

//do regular stuff after;
}

これを行うにはどうすればよいですか(おそらくブースト機能などを使用して)?

4

1 に答える 1

2

FunctionObjectタイプがの場合boost::function<void()>、 の結果からこれに割り当てることができます。次のboost::bindようになります。

boost::function<void()> f = boost::bind(&Manager::someMethod, this);
Base *b = new A(f);

A のコンストラクターには signature がありますA(boost::function<void()>)。を呼び出すとboost::function、仮想関数呼び出しよりもオーバーヘッドがわずかに大きくなります。

特定の状況について確実に知るには十分ではありませんが、 f の機能を表す抽象基本クラスを実際に定義し、コンストラクターを持ち、抽象のオブジェクトを取得すると、より良いインターフェイスになる可能性がBaseありAます代わりに、次のような基本クラス:-

struct ThingDoer
{
    virtual void do() = 0;
};

class Manager : private ThingDoer
{
    virtual void do()
    { ... }

    void createThing()
    {
        Base *b = new A(this);
    }
};

A のコンストラクターには signature がありますA(ThingDoer*)

以前に「デリゲート」設計パターンについて読んだことがあれば、私が言いたいことの種類を知っているでしょう。この単純で抽象的な例では、 を使用したソリューションよりも不格好で長く見えますboost::functionが、実際のソフトウェアには潜在的な利点があります。

  • ThingDoer「デリゲート」タイプ、そのタイプの実装、およびその中の関数に名前を付けることができます。また、Doxygen やその他の構造化されたコメント システムを使用する場合は、関数オブジェクトのパラメーターよりもデリゲート クラスを文書化する方がはるかに簡単です。
  • Managerクラスおよび派生クラスで、から継承するか、ThingDoerThingDoer を継承するネストされた (プライベートまたは保護された) クラスを持つかを選択できます。
  • 後でインターフェースに別の関数を追加したい場合 (2 つの異なることを実行させるため) は、それを行う方が簡単であり、単純に関数オブジェクトをどんどん追加したくなることはありません。(ただし、この方法でコードを作成するための追加コストを既に支払っているため、後で簡単になるだけです。)
  • Java または C# コミュニティのプログラマーは、おそらくこのようなコードに精通しているでしょう。

あなたの状況では、これらのどれも利点がないかもしれません。その場合、間違いなくboost::function/boost::bindソリューションを使用してください。私は似たような状況で同じことをしました。おそらく、C++11 には関数バインディング機能のほとんどまたはすべてが含まれていることにも言及する必要がありstd::ます。

于 2012-06-26T20:01:15.100 に答える