我正试图找出一种可以在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.
};
有谁能建议我如何实现我想做的事情?我真的很困惑我该做什么......
答案 0 :(得分:2)
示例中的信号槽是非虚拟成员函数,它不访问任何对象成员。非虚函数地址在编译时解析,这里不需要this
指针 - 所以没有理由崩溃。
另一方面,您可以使用单一“跟踪”功能自动断开插槽。请参阅以下内容:Boost.Signals中的跟踪;跟踪Boost.Signal2。
答案 1 :(得分:1)
为什么它仍然有效?
实际上是未定义的行为,因为在被破坏的对象上调用了doSomething()
。 (要看到这一点,请在析构函数中添加一个print语句。)运行程序时,“Testing”被打印到屏幕上,但程序可能已崩溃。
您可以考虑将connection
成员添加到SomeClass
。这样,在SomeClass
析构函数中,您可以断开信号槽连接。
答案 2 :(得分:0)
至少回答一些问题:
为什么它仍然有效?我不应该得到某种运行时错误,或者根本不调用该方法吗?
我猜你很幸运。你的对象被破坏了,你仍然可以调用它上面的方法。它是未定义的行为,但在您的情况下它不会崩溃。
您对要解决的问题并不十分具体。因此很难说出什么是最佳解决方案
对于您的委托方法,请查看std::shared_ptr
和std::weak_ptr
。您可以保存std::weak_ptr
数组,并通过这些数组呼叫您的代表。
或许boost::signal
是正确的选择。看看scoped connections。