2012-12-24 30 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()(通常是不小心)在析構函數中增加建立這樣一個錯誤的機會。當然,如果你能以某種方式保證沒有任何現在或將來的代碼在銷燬期間實際上會觸發任何插槽,那麼它完全可以安全地釋放析構函數,但它很難給出這樣的保證,並且我會建議儘可能避免它。

相關問題