2016-01-20 77 views
1

我試圖理解和使用RAII,並希望在此實施意見:RAII和Qt信號

我想RAII PauseProcessRAII發出信號,另外一個在析構函數。例如:

// Header 
public: 
    PauseProcessRAII(QObject *parent = 0); 
    void Execute(); 
    ~PauseProcessRAII(); 

signals: 
    void PauseProcess(bool pause_process); 

// Source 

PauseProcessRAII::~PauseProcessRAII() 
{ 
    emit PauseProcess(false); 
} 

void PauseProcessRAII::Execute() 
{ 
    emit PauseProcess(true); 
} 

// MainWindow code 
void MainWindow::OnPauseProcessRAII(bool pause_process) 
{ 
    qDebug() << "pause_process: " << pause_process; 
} 

void MainWindow::OnButtonSaveClicked() 
{ 
    PauseProcessRAII pauseProcessRAII(this); 
    connect(&pauseProcessRAII, &PauseProcessRAII::PauseProcess, this, &MainWindow::OnPauseProcess); 
    pauseProcessRAII.Execute(); 

    // ... Some code runs 
    // ... pauseRAII desctructor is called 
} 

當我運行代碼都發射如預期的射擊。我的問題是這是一個好的解決方案?起初我雖然PauseProcessRAII析構函數中的emit調用不起作用,因爲它可能已經破壞了信號和插槽連接。當然,這意味着我將不得不將連接添加到我使用它的每個函數中。

+2

這不是一個RAII成語。在RAII中,資源在構造函數中獲取並在析構函數中銷燬。我在構造函數中沒有看到任何資源獲取(我準備考慮發出一種資源管理形式的信號)。同樣,每個RAII課程都必須仔細考慮複製,移動和分配政策,而且我也沒有在這裏看到它。 – SergeyA

+0

除了將事件連接到主窗口外,此處沒有資源。因此,部分轉讓所有權是有問題的(可能是一個可疑的QT設計) –

+0

起初,我要在構造函數中發出信號,但連接尚未完成,因此不會觸發。謝謝,我想我有更多的閱讀要做。我拿走了有關RAII的想法是在堆棧上創建它,所以當函數超出範圍時,析構函數將被調用。我需要這種事情發生,但發出信號,而不是 – adviner

回答

0

如果您的前提是「某些代碼運行」所指示的代碼運行時間足夠長以阻止GUI,那麼整個想法就會被徹底破壞。如果是這樣:不要這樣做。應該在GUI線程中執行的唯一代碼是短的,從運行到完成的代碼,用戶不會注意到足夠長的時間。

如果「某些代碼運行」所花費的時間非常短 - 最長爲幾毫秒 - 那麼您當然可以使用這樣的結構。 RAII這個術語在這裏不適用,因爲你正在處理某種示範警衛。

如果你願意,你可以放棄execute方法並執行構造函數中的連接:

// https://github.com/KubaO/stackoverflown/tree/master/questions/scopeguard-signal-34910879 
// main.cpp 
#include <QtCore> 

class ScopeSignaller : public QObject { 
    Q_OBJECT 
public: 
    Q_SIGNAL void inScope(bool); 
    template <typename F> 
    ScopeSignaller(QObject * target, F && slot, QObject * parent = 0) : QObject(parent) { 
     connect(this, &ScopeSignaller::inScope, target, std::forward<F>(slot)); 
     inScope(true); 
    } 
    ~ScopeSignaller() { 
     inScope(false); 
    } 
}; 

int main(int argc, char ** argv) { 
    QCoreApplication app{argc, argv}; 
    ScopeSignaller s(&app, +[](bool b){ qDebug() << "signalled" << b; }); 
} 

#include "main.moc"