2

次の状況があります(コードの方が優れています)

    class Foo
    {
private:
       typedef boost::signal<void ()> Signal;
       Signal signal;

public:
       void Register_SignalFunction(const Signal::slot_type& slot);
       void Unregister_SignalFunction(const Signal::slog_type& slot);
    }

    class OtherFoo
    {
       Foo foo;
public:
       OtherFoo()
       {
            foo.Register_SignalFunction(&OnSignal)    //I know I can't do this that is precisely my question.
       }

       void OnSignal();  //what to do when signal fires
     }  

問題は、「メンバー関数」ポインターを Register メソッドに渡す方法です。また、これは大丈夫ですか?私が欲しい/必要としているのは、ある種の代理人登録システムです。誰かが私を正しい方向に向けることができれば、感謝します。事前にサンクス。

4

4 に答える 4

4

通常はブースト バインドを使用します。

foo.Register_SignalFunction(boost::bind(&OtherFoo::OnSignal, this));

何が起きてる?:-)

シグナルの接続メソッドは、ファンクターを取ります。これは () 演算子を実装するオブジェクトです。bind は、関数ポインター (解放関数またはメンバー関数のいずれか) を受け取り、正しいシグネチャを持つファンクターを返します。

こちらもご覧ください:

Boost::Signals を使用した C++ イベンティングの完全な例

そしてここ:

boost::function と boost::bind の仕組み

信号を切断するには、connect からの戻り値を次のように格納します。

boost::signals::connection

そして、その上で切断メソッドを呼び出します。

于 2011-08-23T05:05:54.660 に答える
1

通常、次のいずれかを行います。

void Register_SignalFunction(const boost::function<void()> &slot) {
    signal += slot;
}

または、インライン関数として:

template<typename T>
void Register_SignalFunction(T &slot) {
    signal += slot;
}

後者は、間接的なレイヤーを削除することでわずかに効率的かもしれませんが、内部で使用しないとboost::function仮定するだけです(そうなる可能性があります)。だから、本当に好きな方を使ってください。boost::signalboost::function

于 2011-08-23T04:17:07.103 に答える
0

たくさん試した後、動作しました。コードは次のとおりです。

GraphicsDeviceManager
{
  private:
      typedef boost::signal<void ()> DeviceLost;
      DeviceLost deviceLost;

  public:
      Register_DeviceLostHandler(const boost::function<void ()> &handler)
      {
          deviceLost.connect(slot);
      }
      Unregister_DeviceLostHandler(const boost::function<void ()> &handler)
      {
          //deviceLost.disconnect(slot); 
      }
}

class GameBase
{
  private:
    GraphicsDeviceManager* graphics;

   public:
       GameBase()
       {
          graphics = new GraphicsDeviceManager();
          graphics->Register_DeviceLostHandler(boost::bind(&GameBase::OnDeviceLost, this));
       }
       void OnDeviceLost()
       {
           //do some stuff
       }
}

このコードは正常に機能しますが、1つの例外を除いて、deviceLost.disconnect(handler)ステートメントのコメントを外すと、次のようなコンパイルエラーが発生します。エラーC266 "boost :: operator ==":4つのオーバーロードでも同様の変換が行われます。

それで、なぜこれが起こっているのですか?私がしようとしていることを達成する他の方法を知っていますか?

于 2011-08-23T17:38:42.610 に答える