2012-04-09 12 views
12
try 
{ // `count()` throws exception 
    connect(thread, SIGNAL(started()), engine, SLOT(count())); 
} 
catch(const X& e) 
{} 

Come di Qt-5, ottengo l'errore seguente:Come catturare le eccezioni in Qt?

Qt has caught an exception thrown from an event handler. Throwing exceptions from an event handler is not supported in Qt. You must not let any exception whatsoever propagate through Qt code. If that is not possible, in Qt 5 you must at least re-implement QCoreApplication::notify() and catch all exceptions there.

Se non riesco a cogliere le eccezioni in modo convenzionale come indicato sopra, allora dove dovremmo prendere quelli?

+0

Forse si dovrebbe mettere il blocco try-catch nella funzione count(). .. – Kobe

+0

#vBx count thea – smallB

+1

Quindi la soluzione fornita nella domanda è buona – Kobe

risposta

8

where am I supposed to catch it?

Questo è esattamente il motivo per Qt non supporta generare eccezioni attraverso le connessioni del segnale/di slot. Se lo provate, vedrete questo messaggio:

Qt has caught an exception thrown from an event handler. Throwing exceptions from an event handler is not supported in Qt. You must reimplement QApplication::notify() and catch all exceptions there.

Come si parla, è possibile creare una sottoclasse QApplication e riprendere eccezione lì, ma che sarà un modo molto fastidioso di gestire le cose.

Se possibile, suggerirei di riscrivere il numero in modo che non venga generato.


Cosa succede se non si può riscrivere count()?

Ad esempio, che succede se count() fa parte di una funzione in una libreria di terze parti che stai utilizzando?

Non esiste alcun slot in una libreria Qt ufficiale, quindi se si utilizza una libreria di terze parti con uno slot che genera, è probabilmente un segno che non è una buona libreria. Se si desidera utilizzarlo comunque, è consigliabile che anziché acquisirlo in QApplication::notify, invece di creare un adattatore.

Che cosa significa? Per prima cosa crea un oggetto che acquisisce il tuo oggetto di terze parti abbozzato nel costruttore. In esso, scrivi uno slot che avvolge una chiamata allo slot di lancio con un blocco try/catch. Ora invece di collegarti allo slot dell'oggetto di terze parti abbozzato, connettiti allo slot dell'oggetto appena creato.

Facendo l'eccezione che cattura in questo modo mantiene il codice correlato insieme e impedisce a QApplication::notify di riempirsi con un gruppo di blocchi try/catch non collegati se si verifica più di una di queste funzioni problematiche.

Ad esempio:

class BadCounter { 
Q_OBJECT 
public slots: 
    void count() { throw CounterError("unable to count"); } 
}; 

class CounterAdaptor { 
Q_OBJECT 
    BadCounter* counter_; 
public: 
    CounterAdaptor(BadCounter* counter) { 
    counter_ = counter; 
    } 
public slots: 
    void count() { 
    try { 
     counter_->count(); 
    } catch (const CounterError& e) { 
     std::cerr << e.what() << std::endl; 
    } 
    } 
}; 

int main() { 
    BadCounter engine; 
    CounterAdaptor adaptor(&engine); 
    QThread* thread = new QThread(); 
    connect(thread,SIGNAL(started()),&adaptor,SLOT(count())); 
    thread.start(); 
    ... // etc... 
    delete thread; 
} 

Che cosa succede se si desidera gestire qualcosa che potrebbe essere gettato da qualche parte?

L'ovvio esempio di questo tipo di preoccupazione globale è un'eccezione imprevista. Gli errori possono accadere ovunque. Sarebbe auspicabile registrare quanti più dettagli possibile sull'evento, in modo che la causa potesse essere identificata e corretta. In questo caso, è che desidera reimplementare QApplication::notify nella propria sottoclasse come mostrato in jichi's answer. Usare un gestore globale per le preoccupazioni globali è abbastanza ragionevole.

+0

sì, credo che dovrò riscrivere questo e non buttare. Grazie. – smallB

+0

È possibile chiamare 'count()', salvare il risultato, quindi passare il risultato a 'SLOT' se 'SLOT' non è autorizzato a lanciare un'eccezione. –

+0

SLOT non accetta il risultato di count(). Questa è la macro SLOT: '# definisce SLOT (a)" 1 "# a' – cgmb

-8

Si può provare questo per un esempio, vedere che la soluzione è buona:

int f() 
{ 
    throw 1; 
    return 5; 
} 

void g(int x) 
{ 
    cout << x << endl; 
} 

int main() 
{ 
    try { 
      g(f()); 
    }catch(int) 
    { 
     cout << "Caught exception" << endl; 
    } 
} 
+0

#vBx non si utilizza alcuna connessione segnali/slot, mi manca qualcosa? – smallB

+0

@smallB: i segnali e gli slot sono costrutti specifici per QT, ciò che vBx offre qui è la soluzione standard C++. –

+0

@Als Lo vedo, ma la mia domanda è specifica per qt. Pensavo che la nozione di slot del segnale sarebbe stata una buona rivelazione. Inoltre se vuoi notare non chiedo come usare try catch block. – smallB

6

Se qualcuno ha bisogno di un codice di esempio per eseguire l'override QApplication :: Notify, ho avuto uno da qui (in giapponese): http://www.02.246.ne.jp/~torutk/cxx/qt/QtMemo.html

#include "MyApplication.h" 
#include <exception> 

MyApplication::MyApplication(int& argc, char** argv) : 
    QApplication(argc, argv) {} 

bool MyApplication::notify(QObject* receiver, QEvent* event) { 
    bool done = true; 
    try { 
    done = QApplication::notify(receiver, event); 
    } catch (const std::exception& ex) { 
    // ログや何らかの回復処理 
    } catch (...) { 
    // ログや何らかの回復処理 
    } 
    return done; 
} 
+0

Che cos'è MyApplication? È una finestra di dialogo? – Petr

+1

classe MyApplication: public QApplication – jichi

+0

funziona, grazie – Petr

Problemi correlati