0

C++で他のオブジェクトにメッセージを送信する方法を見つけようとしています。たとえば、オブジェクトが別のオブジェクトと衝突すると、衝突が発生したというメッセージが送信されます。私はboost:signalを使おうとしていますが、間違った方法で使用している場合を除いて、正確には私が望んでいるものではないようです。

主な理由は次のとおりです。

スタックに割り当てたオブジェクトが破棄されたとしても、このコードが機能する理由はよくわかりません...

class SomeClass
{
public:

   void doSomething()
   {
      std::cout << "Testing\n";
   }
};


int main(int argc, char** argv)
{
     boost::signal<void ()> sig;


     {
           SomeClass obj;
           sig.connect(std::bind(&SomeClass::doSomething, &obj));
     }

     sig();
}

さて、コードは次のように出力します。

Testing

なぜそれでも機能するのですか?ある種の実行時エラーが発生したり、メソッドがまったく呼び出されなかったりするべきではありませんか?私はそれが実際に起こることを本当に望んでいません、私はオブジェクトが破壊されるとすぐに接続が失われることを望みます。

私は別の方法でメッセージを送信することを考えていました。おそらく、デリゲートのタイプを使用するObjective-Cスタイルで、クラスから継承してメッセージを送信します。しかし、繰り返しになりますが、複数のデリゲートが必要な場合はデリゲートポインターの配列が必要であり、デリゲートが破棄された場合はその配列から削除する必要があるなど、混乱を招くようです...混乱を引き起こします。

例えば

class ColliderDelegate
{
public:

    virtual ~ColliderDelegate() {}

    virtual void onCollisionEnter(Collider* sender, Collider* withWho) = 0;
    virtual void onCollisionExit(Collider* sender, Collider* withWho) = 0;
    virtual void onCollisionStay(Collider* sender, Collider* withWho) = 0;

private:

    // I would have to have an array of Collider's that this object is connected to,
    // so it can detatch itself when it's destroyed...
 };

 class Collider
 {
 public:
    void add(ColliderDelegate* delegate);
    void remove(ColliderDelegate* delegate);


    void checkForCollisionWith(Collider*);

 private:

     // I would have to have an array of ColliderDelegate's that this object
     // needs to send information to.
 };

誰かが私がやりたいことをどのように実装できるか提案できますか?私は私が何をすべきかについて本当に混乱しています...

4

3 に答える 3

2

あなたの例のシグナルスロットは、オブジェクトメンバーにアクセスしない非仮想メンバー関数です。非仮想関数のアドレスはコンパイル時に解決されますthis。ここではポインターは必要ありません。したがって、クラッシュの理由はありません。

一方、信号の「追跡」機能を使用して、スロットを自動的に切断することもできます。以下を参照してください: Boost.Signalsで追跡します。Boost.Signal2で追跡します。

于 2012-07-15T12:04:50.907 に答える
1

なぜそれはまだ機能しますか?

doSomething()破壊されたオブジェクトで呼び出されているため、実際には未定義の動作です。(これを確認するには、デストラクタに print ステートメントを追加します。) プログラムを実行すると、"Testing" が画面に出力されましたが、プログラムがクラッシュした可能性があります。

connectionにメンバーを追加することを検討してくださいSomeClass。このようにして、SomeClassデストラクタでシグナルとスロットの接続を切断できます。

于 2012-07-15T12:04:31.787 に答える
0

あなたの質問の少なくともいくつかに答えるには:

なぜそれはまだ機能しますか?なんらかの実行時エラーが発生したり、メソッドをまったく呼び出さなかったりするべきではありませんか?

あなたはただラッキーだと思います。オブジェクトは破棄されますが、メソッドを呼び出すことはできます。これは未定義の動作ですが、あなたの場合はクラッシュしません。

どの問題を解決したいのか、あまり具体的ではありません。そのため、何が最善の解決策であるかを判断するのは困難です。デリゲート アプローチについては、と
をご覧ください。の配列を保持し、それらを介してデリゲートを呼び出すことができます。std::shared_ptrstd::weak_ptrstd::weak_ptr

または多分boost::signal正しい選択です。スコープ接続を見てください。

于 2012-07-15T12:04:18.757 に答える