2012-12-24 28 views
11

当一个QObject派生的对象被破坏时,可以从其析构函数发出一个信号吗?我尝试了它,它似乎工作,但我不知道是否应该完成。可以在Qt中从对象的析构函数发出信号吗?

例如,该代码

class MyClass : public QObject { 
signals: 
    void mySignal(const QString &str); 
public: 
    QString myString; 
    ~MyClass() { emit mySignal(myString); } 
} 

将通过一个常量引用的对象被执行的连接槽时,可能是超出范围由时间。

回答

13

排放通常很好(QObject对“已销毁”信号也是这样做的),包括一个与您的情况一样的情况。当连接是直接的,字符串仍然活着。当它是QueuedConnection时,则该字符串首先被复制到事件循环中。

+0

但我认为sender()方法可能会给一个无效的指针?无论如何,我认为在编写插槽时我应该小心并记住这一点。 – sashoalm

+3

是的,当然。如果你有一个排队的连接,如果信号在dtor发出,你不能使用sender()。信号的接收器必须知道这一点。 –

0

如果你问是否可以:是的,它本身不会引起任何问题。

如果你会问,如果它在Qt中做一个普遍安全的事情?绝对不安全。如果你从析构函数中发出,你必须非常谨慎,并且对Qt事件系统有很好的理解。

请记住,当一个QObject后代破坏,它会断开所有信号,所以被破坏的对象不会在他们的插槽上得到更多的调用?那么有一个问题:破坏秩序。析构函数确实断开连接,并且它是最后的破坏,意思是在销毁链中,事件可能仍然到达“半死”对象,在访问虚函数和已经被破坏的后代成员时导致访问违规。可能性存在,如果你使用的事件系统,以及任何这些条件都满足:

  • 在多线程环境中,如果对象不是在自己的线程破坏。
  • 在多线程环境中,如果对象的销毁链触发在任何运行路径上运行processEvents()
  • 在多线程环境中,如果另一个线程上的任何对象与此对象有直接连接,并且它无法直接连接对其销毁信号作出反应。
  • 在单线程环境中,析构函数发送信号 可能会返回到直接连接链中的对象。

我“死亡期间的生活”称这种效果,信号冒落或运行任何形式的processEvents()(通常是不小心)在析构函数中增加建立这样一个错误的机会。当然,如果你能以某种方式保证没有任何现在或将来的代码在销毁期间实际上会触发任何插槽,那么它完全可以安全地释放析构函数,但它很难给出这样的保证,并且我会建议尽可能避免它。

相关问题