boost :: signal和std :: bind混淆,我应该尝试别的吗?

时间:2012-07-15 11:32:34

标签: c++ boost

我正试图找出一种可以在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样式,您将从类继承以向您发送消息。但话说回来,它似乎导致我一些混乱,例如,如果我想要多个委托,我会有一个委托指针数组,如果一个委托被破坏,我将不得不从该数组中删除...哪个可以引起一些困惑。

e.g。

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.
 };

有谁能建议我如何实现我想做的事情?我真的很困惑我该做什么......

3 个答案:

答案 0 :(得分:2)

示例中的信号槽是非虚拟成员函数,它不访问任何对象成员。非虚函数地址在编译时解析,这里不需要this指针 - 所以没有理由崩溃。

另一方面,您可以使用单一“跟踪”功能自动断开插槽。请参阅以下内容:Boost.Signals中的跟踪;跟踪Boost.Signal2

答案 1 :(得分:1)

  

为什么它仍然有效?

实际上是未定义的行为,因为在被破坏的对象上调用了doSomething()。 (要看到这一点,请在析构函数中添加一个print语句。)运行程序时,“Testing”被打印到屏幕上,但程序可能已崩溃。

您可以考虑将connection成员添加到SomeClass。这样,在SomeClass析构函数中,您可以断开信号槽连接。

答案 2 :(得分:0)

至少回答一些问题:

  

为什么它仍然有效?我不应该得到某种运行时错误,或者根本不调用该方法吗?

我猜你很幸运。你的对象被破坏了,你仍然可以调用它上面的方法。它是未定义的行为,但在您的情况下它不会崩溃。

您对要解决的问题并不十分具体。因此很难说出什么是最佳解决方案 对于您的委托方法,请查看std::shared_ptrstd::weak_ptr。您可以保存std::weak_ptr数组,并通过这些数组呼叫您的代表。

或许boost::signal是正确的选择。看看scoped connections