どこで捕まえればいいの?
これがまさに、Qt がシグナル/スロット接続を介した例外のスローをサポートしていない理由です。試してみると、次のメッセージが表示されます。
Qt は、イベント ハンドラーからスローされた例外をキャッチしました。Qt では、イベント ハンドラーからの例外のスローはサポートされていません。QApplication::notify() を再実装し、そこですべての例外をキャッチする必要があります。
言及されているように、QApplication をサブクラス化してそこで例外をキャッチすることは可能ですが、それは物事を処理する非常に面倒な方法になります。
可能であれば、スローしないように count を書き換えることをお勧めします。
count() を書き換えられない場合はどうなりますか?
たとえば、count() が、使用しているサードパーティ ライブラリの関数の一部である場合はどうなるでしょうか?
公式の Qt ライブラリにはスロットがスローされないため、スロットがスローされるサードパーティ製ライブラリを使用している場合は、それが適切なライブラリではないことを示している可能性があります。とにかく使いたい場合は、 でキャッチするのではなく、QApplication::notify
代わりにアダプターを作成することをお勧めします。
どういう意味ですか?まず、大ざっぱなサードパーティ オブジェクトをコンストラクターに取り込むオブジェクトを作成します。その中に、try/catch ブロックを使用してスローするスロットへの呼び出しをラップするスロットを記述します。大ざっぱなサードパーティ オブジェクトのスロットに接続する代わりに、新しく作成したオブジェクトのスロットに接続します。
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