「Qtの基礎 - 例外処理」の版間の差分
(ページの作成:「== 概要 == <br><br> == 全ての例外をキャッチする方法 == 標準の設定では、NULLポインタのアクセスや0除算等で発生する例外をキ…」) |
(→概要) |
||
1行目: | 1行目: | ||
== 概要 == | == 概要 == | ||
<br><br> | |||
== QExceptionクラス == | |||
==== QExceptionクラスとは ==== | |||
<code>QException</code>クラスは、スレッド間で転送可能な例外の基底クラスを提供する。<br> | |||
<br> | |||
<code>QtConcurrent</code>クラスは、<code>QException</code>クラスを継承しており、2つのヘルパー関数を実装することにより、<br> | |||
スレッドの境界を越えて例外をスローおよびキャッチすることをサポートする。<br> | |||
<code>QException</code>クラスを継承したサブクラスは、値によってスローされ、参照によってキャッチする必要がある。<br> | |||
<syntaxhighlight lang="c++"> | |||
class SampleException : public QException | |||
{ | |||
public: | |||
void raise() const override | |||
{ | |||
throw *this; | |||
} | |||
SampleException *clone() const override | |||
{ | |||
return new SampleException(*this); | |||
} | |||
}; | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="c++"> | |||
try | |||
{ | |||
QtConcurrent::blockingMap(list, throwFunction); // throwFunctionはSampleExceptionをスローする関数とする | |||
} | |||
catch (SampleException &e) | |||
{ | |||
// handle exception | |||
// ...略 | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
<code>QException</codE>クラスを継承したサブクラスではない例外を投げる場合、Qtの関数は受信側のスレッドで<code>QUnhandledException</code>クラスを投げる。<br> | |||
<br> | |||
<code>QFuture</code>クラスを使用する場合、以下に示す関数を呼び出すと、転送された例外がスローされる。<br> | |||
* QFuture::waitForFinished() | |||
* QFuture::result() | |||
* QFuture::resultAt() | |||
* QFuture::results() | |||
<br> | |||
==== QExceptionクラスのメンバ関数 ==== | |||
* <code>clone</code>関数 | |||
<syntaxhighlight lang="c++"> | |||
QException *QException::clone() const | |||
</syntaxhighlight> | |||
<br> | |||
<code>QException</code>クラスを継承したサブクラスにおいて、<code>clone</code>関数を以下のようにオーバーライドする。<br> | |||
<syntaxhighlight lang="c++"> | |||
SampleException *SampleException::clone() const | |||
{ | |||
return new MyException(*this); | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
* <code>raise</code>関数 | |||
<syntaxhighlight lang="c++"> | |||
void QException::raise() const | |||
</syntaxhighlight> | |||
<br> | |||
<code>QException</code>クラスを継承したサブクラスにおいて、<code>raise</code>関数を以下のようにオーバーライドする。<br> | |||
<syntaxhighlight lang="c++"> | |||
void MyException::raise() const | |||
{ | |||
throw *this; | |||
} | |||
</syntaxhighlight> | |||
<br><br> | <br><br> | ||
2022年12月8日 (木) 06:13時点における版
概要
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
オプションが付加される。
この状態で、上記のサンプルコードを実行すると、例外をキャッチすることができる。