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

、私は次のエラーを取得:上記のように、私は従来の方法で例外をキャッチすることができない場合どのようにQtの中に例外をキャッチするには? Qtの-5のよう

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.

を、そしてどこにそれらをキャッチすることになっていますか?

+0

たぶん、あなたは、count()関数でtry-catchブロックを置く必要があります。 .. – Kobe

+0

#vBxカウントスロー – smallB

+1

質問で提供されたあなたの解決策は良いです – Kobe

答えて

8

where am I supposed to catch it?

Qtはシグナル/スロット接続を介し例外をスローサポートしていない理由はまさにです。あなたはそれをしようとすると、このメッセージが表示されます:それは言及したよう

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.

を、はQApplicationをサブクラス化し、そこにあなたの例外をキャッチすることが可能であるが、それは物事を処理する非常に迷惑な方法になります。

可能ならば、私はそれをスローしないように、カウントを書き換えることをお勧めします。


count()を書き換えられない場合はどうすればよいですか?例えば

、カウント数(サードパーティのライブラリ内の関数の一部は、あなたは何を)使用しているされている場合は?公式Qtライブラリで

ませスロットはスローなので、あなたがスロースロットでサードパーティのライブラリを使用している場合、それはおそらく、それは良いライブラリーではないというサインです。あなたはとにかくそれを使用したい場合、私はあなたの代わりにアダプターを作成することを、QApplication::notifyでそれを引くのではなく、それをお勧めします。

これはどういう意味ですか?最初に、コンストラクタでスケッチしたサードパーティオブジェクトを取り込むオブジェクトを作成します。その中に、try/catchブロックで投げスロットへの呼び出しをラップするスロットを書きます。今、代わりに大ざっぱサードパーティのオブジェクトのスロットに接続するので、新しく作成したオブジェクトのスロットに接続します。

このように例外をキャッチすると、関連するコードがまとめられ、これらの問題のある関数が2つ以上ある場合は、QApplication::notifyが無関係のtry/catchブロックでいっぱいになるのを防ぎます。例えば

:あなたはどこからでもスローされる可能性が何かを処理したい場合はどう

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; 
} 

このようなグローバルな問題の明白な例は、予期しない例外です。間違いはどこでも起こり得る。原因を特定して修正できるように、できるだけ多くのイベントの詳細を記録することが望ましいでしょう。この場合、jichi's answerのように独自のサブクラスでQApplication::notifyを再実装します。グローバルな問題にグローバルハンドラを使用することはかなり妥当です。誰かがはQApplicationを上書きするサンプルコードを必要とする場合

+0

はい、私はこれを書き直す必要があり、投げないと信じています。ありがとう。 – smallB

+0

'count()'を呼び出して結果を保存し、 'SLOT'が例外をスローすることができない場合は結果を' SLOT'に渡すことは完全に可能です。 –

+0

SLOTはcount()の結果を受け取りません。これはSLOTマクロです: '#define SLOT(a)" 1 "#a' – cgmb

-8

あなたはあなたのソリューションが良好であることを確認するために、例えばこれを試すことができます。

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信号/スロット接続を使用していませんが、何か不足していますか? – smallB

+0

@smallB:シグナルとスロットはQT固有の構造体ですが、ここでvBxが提供するものは標準のC++ソリューションです。 –

+0

@Als私はそれを参照してくださいが、私の質問はQTに固有です。私はシグナルスロットの概念が良い放棄されると思った。また、私はtry catchブロックを使用する方法を尋ねないことに注意してください。 – smallB

6

::通知し、私は(日本では)ここから1つを得た: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

MyApplicationとは何ですか?それはダイアログですか? – Petr

+1

クラスMyApplication:public QApplication – jichi

+0

ありがとう、 – Petr

関連する問題