2016-01-20 5 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 
} 

Когда я запускаю код, оба испускают огонь, как ожидалось. Мой вопрос - это хорошее решение? Сначала я, хотя вызов emit в дескрипторе PauseProcessRAII не работал бы, потому что он мог уничтожить соединение с сигналом и слотом. Конечно, это означало бы, что я должен добавить подключение к каждой функции, в которой я его использую.

+2

Это не RAII идиома. В RAII ресурс приобретается в конструкторе и уничтожается в деструкторе. Я не вижу каких-либо ресурсов в конструкторе (я готов рассмотреть возможность передачи сигнала в виде управления ресурсами). Также каждый класс RAII должен тщательно продумать политику копирования, перемещения и назначения, и я тоже не вижу его здесь. – SergeyA

+0

Здесь нет ресурсов помимо подключения события к главному окну. Следовательно, передача права собственности частично является сомнительной (возможно, сомнительной конструкцией QT) –

+0

Сначала я собирался испустить сигнал в конструкторе, но соединение еще не создано, поэтому оно не срабатывает. Спасибо, я думаю, у меня есть больше чтения, чтобы сделать это. Я забрал идею о том, что RAII создавал ее в стеке, поэтому, когда функция выходит за пределы области, будет вызван деструктор. И мне нужно, чтобы это произошло, но вместо этого испустил сигнал. – adviner

ответ

0

Вся идея принципиально нарушена, если ваша предпосылка заключается в том, что код, обозначенный «Some code running», работает достаточно долго, чтобы блокировать 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"