「Qtの基礎 - 例外処理」の版間の差分

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動
(ページの作成:「== 概要 == <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オプションが付加される。
この状態で、上記のサンプルコードを実行すると、例外をキャッチすることができる。