Qtの基礎 - 例外処理
概要
QExceptionクラス
QExceptionクラスとは
QException
クラスは、スレッド間で転送可能な例外の基底クラスを提供する。
QtConcurrent
クラスは、QException
クラスを継承しており、2つのヘルパー関数を実装することにより、
スレッドの境界を越えて例外をスローおよびキャッチすることをサポートする。
QException
クラスを継承したサブクラスは、値によってスローされ、参照によってキャッチする必要がある。
class SampleException : public QException
{
public:
void raise() const override
{
throw *this;
}
SampleException *clone() const override
{
return new SampleException(*this);
}
};
try
{
QtConcurrent::blockingMap(list, throwFunction); // throwFunctionはSampleExceptionをスローする関数とする
}
catch (SampleException &e)
{
// handle exception
// ...略
}
QException
クラスを継承したサブクラスではない例外を投げる場合、Qtの関数は受信側のスレッドでQUnhandledException
クラスを投げる。
QFuture
クラスを使用する場合、以下に示す関数を呼び出すと、転送された例外がスローされる。
- QFuture::waitForFinished()
- QFuture::result()
- QFuture::resultAt()
- QFuture::results()
QExceptionクラスのメンバ関数
clone
関数
QException *QException::clone() const
QException
クラスを継承したサブクラスにおいて、clone
関数を以下のようにオーバーライドする。
SampleException *SampleException::clone() const
{
return new MyException(*this);
}
raise
関数
void QException::raise() const
QException
クラスを継承したサブクラスにおいて、raise
関数を以下のようにオーバーライドする。
void MyException::raise() const
{
throw *this;
}
全ての例外をキャッチする方法
標準の設定では、NULLポインタのアクセスや0除算等で発生する例外をキャッチすることができない。
char *p = nullptr;
try
{
qDebug() << "try";
*p = 'A';
}
catch(...)
{
qDebug() << "catch";
}
qmakeで生成されたMakefileを見ると、-EHsc
オプションが付加されている。
/EHs
または/EHsc
を使用する場合、catch
句では、非同期構造化例外がキャッチされない。
構造化例外とは、ハードウェア例外を含むシステム的な例外のことで、
Windowsでは、SEH(Structured Exception Handling : 構造化例外処理)という仕組みが提供されている。
全ての例外をキャッチするには、プロジェクトファイル(.pro)に、以下の設定を追記する。
win* { QMAKE_CXXFLAGS_EXCEPTIONS_ON = /EHa QMAKE_CXXFLAGS_STL_ON = /EHa } linux* { QMAKE_CXXFLAGS_EXCEPTIONS_ON = /EHa QMAKE_CXXFLAGS_STL_ON = /EHa }
ビルドして生成されたMakefileには、上記で設定した-EHa
オプションが付加される。
この状態で、上記のサンプルコードを実行すると、例外をキャッチすることができる。