c++異常処理メカニズムの例と詳細な説明

6358 ワード

この2,3日私はc++異常処理メカニズムをテストする例を書いて、とても良い模範的な作用があると感じて、ここで貼って、c++異常処理の初心者に入門します.本文の後にc++という異常な知識が普及しているので、興味のある方も見てみましょう.次のコードはあなたのconsoleプロジェクトに直接貼って、デバッグを実行して効果を見て、c++の異常メカニズムを分析することができます.
 
  
#include "stdafx.h"
#include
#include
#include 
// 
#define _CRTDBG_MAP_ALLOC 
#ifdef _DEBUG
#define new new(_NORMAL_BLOCK, __FILE__, __LINE__)
#endif

// 
class MyExcepction
{
public:

//  ,
MyExcepction(int errorId)
{
// 
std::cout <m_errorId = errorId;
}

// 
MyExcepction( MyExcepction& myExp)
{
// 
std::cout <this->m_errorId = myExp.m_errorId;
}

~MyExcepction()
{
// 
std::cout <}

// 
int getErrorId()
{
return m_errorId;
}

private: 
// 
int m_errorId;
};

int main(int argc, char* argv[])
{
// 
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

//  ,
int throwErrorCode = 110;

std::cout <std::cin >> throwErrorCode;

try 
{
if ( throwErrorCode == 110)
{
MyExcepction myStru(110);

//   ->  catch( MyExcepction* pMyExcepction) 
//  catch ,
//  ,
// catch ,myStru
throw &myStru; 
}
else if ( throwErrorCode == 119 )
{
MyExcepction myStru(119);

//  , catch
//  catch( MyExcepction myExcepction) 
//  catch
// throw myStru
throw myStru; 
}
else if ( throwErrorCode == 120 )
{
// 
//  , catch( MyExcepction* pMyExcepction) delete

//  catch( MyExcepction* pMyExcepction) 
MyExcepction * pMyStru = new MyExcepction(120); 
throw pMyStru; 
}
else 
{
// 
//  catch
//  catch
// throw
throw MyExcepction(throwErrorCode); 

}
catch( MyExcepction* pMyExcepction)
{
// 
std::cout <

// 
std::cout <getErrorId()<

//  , , delete
//delete pMyExcepction;
}
catch ( MyExcepction myExcepction)
{
// 
std::cout <

// 
std::cout <}
catch(...)
{
// 
std::cout <

//  ,
throw ;
}

// 
int temp;
std::cin >> temp;

return 0;


知識点:c++異常メカニズム
一、概説
C++自身は非常に強い誤り訂正能力を持っており,現在に至るまで,比較的完全な異常処理メカニズムが確立されている.C++の例外は2つにほかならない.1つは文法エラーである.すなわち、プログラムにエラーが発生した文、関数、構造、クラスであり、コンパイラができない.もう1つは、実行時に発生するエラーで、一般的にアルゴリズムに関連しています.
文法の間違いについては、言うまでもなく、コードを書くときに細かくすれば解決できます.C++コンパイラのエラーメカニズムは、これらのエラーを簡単に解決することができます.
2つ目は、ファイルのオープン失敗、配列の下付きスケールオーバーフロー、システムメモリ不足など、実行時のエラーです.これらの問題が発生すると,アルゴリズムの失効,プログラムの実行時の無断停止などの故障を引き起こすこともよくある.これは、ソフトウェアアルゴリズムを設計する際に包括的であることを要求します.例えば、ファイルのオープンに失敗した場合、保護の方法はいろいろありますが、最も簡単なのは「return」コマンドを使用して、上位呼び出し者に関数の実行に失敗したことを伝えることです.もう1つの処理戦略は,c++の異常メカニズムを用いて異常を放出することである.
二、c++異常処理メカニズム
C++異常処理メカニズムは、実行エラーを効率的に処理するための非常に強力で柔軟なツールであり、より多くの弾力性、安全性、安定性を提供し、従来の方法による問題を克服した.
異常な投げ出しと処理には、try、throw、catchの3つのキーワードが主に使用されます.放出異常とは、異常が発生したか否かを検出するものであり、C++ではthrow文で実現され、異常が発生したと検出されると、異常が放出される.この文のフォーマットは、throw式;try文ブロックのプログラムセグメント(呼び出された関数を含む)に異常が発見され、その異常が破棄された場合、この異常はtry文ブロック後のcatch文によってキャプチャされて処理され、キャプチャおよび処理の条件は、破棄された異常のタイプがcatch文の異常タイプと一致することである.C++はデータ型を用いて異なる異常を区別するため,異常を判断する際にはthrow文における式の値に実用的な意味がなく,式のタイプが特に重要である.try-catch文の形式は次のとおりです.
 
  
try 
{

}

catch(  [ ]) // 
{
}
catch(  [ ]) // 
{
}
catch(...) // 
{


【例1】除数0の異常を扱う.この例では、上記除数0の異常をtry/catch文で異常をキャプチャし、throw文を用いて異常を投げ出すことで異常処理を実現し、実装コードをコードリスト1-1に示す.
//コードリスト1-1
 
  
#include //

#include

double fuc(double x, double y) //
{
if(y==0)
{
throw y; // 0,
}
return x/y; //
}
void main()
{
double res;
try //
{
res=fuc(2,3);
cout<res=fuc(4,0);  ,
}
catch(double) //
{
cerr<exit(1); //
}


【例2】カスタム例外タイプ(本明細書で説明したコード)
三、異常なインタフェース宣言
プログラムの可読性を強化するために、使用する関数がどのような例外を放出するかを、関数のユーザーが容易に知ることができるようにするには、関数の宣言に、この関数が放出する可能性のあるすべての例外タイプをリストします.たとえば、次のようにします.
void fun() throw( A,B,C,D);
これは,関数fun()が可能であり,タイプ(A,B,C,D)およびそのサブタイプの異常のみを放出できることを示している.
関数の宣言に例外のインタフェース宣言が含まれていない場合、この関数はvoid fun()などの任意のタイプの例外を放出できます.
例外のタイプを投げ出さない関数は、次の形式で宣言できます.
void fun() thow();
五、異常処理において注意すべき問題
1.放出された例外が関数取得(catch)されていない場合、c++実行システムにアップロードされ、プログラム全体が終了します.
2.通常、例外放出後にリソースは正常に解放されますが、クラスのコンストラクション関数に例外が放出されると、システムはそのコンストラクション関数を呼び出すことはありません.処理方法は、コンストラクション関数に例外を放出する場合は、放出前に申請したリソースを削除することを覚えておいてください.
3.例外処理は、値ではなくタイプのみで一致するので、catchブロックのパラメータにはパラメータ名がなく、パラメータタイプのみが必要です.
4.関数プロトタイプの異常説明は、実装中の異常説明と一致しなければならない.そうしないと、異常な衝突を引き起こしやすい.
5.throw文の後に異常オブジェクトを書くべき場合、throwはまずCopyコンストラクション関数によって新しいオブジェクトを構築し、その新しいオブジェクトをcatchに渡す. 
では、異常が投げ出された後、新しいオブジェクトはどのように解放されますか?例外処理メカニズムは、例外が放出された新しいオブジェクトが関数スタックに作成されるのではなく、専用の例外スタックに作成されることを保証します.そのため、複数の関数にまたがって上位に渡すことができます.そうしないと、スタックが空になっている間に破棄されます.tryからthrow文の間に構築されたすべてのオブジェクトの構造関数が自動的に呼び出されます.しかし、main関数に遡っても一致するcatchブロックが見つからない場合、システムはterminate()を呼び出してプログラム全体を終了し、この場合、すべてのローカルオブジェクトが正しく破棄されることは保証されません.
6.catchブロックのパラメータは、値伝達ではなくアドレス伝達を推奨し、効率を向上させるだけでなく、オブジェクトの多態性も利用することができる.また,派生クラスの異常キャプチャは親クラスの異常キャプチャの前に置くべきであり,そうでなければ派生クラスの異常はキャプチャできない.
7.異常説明を作成する場合、派生クラスメンバー関数の異常説明とベースクラスメンバー関数の異常説明が一致することを確保する.すなわち、派生クラスが書き換えた虚関数の異常説明は、少なくとも対応するベースクラス虚関数の異常説明と同じで、さらに厳しく、より特殊である.