2012-07-02 3 views

答えて

13

そのサイトは愚かであり、悪いデザインを教えています。

intまたはchar*を投げる場合は、intまたはchar*を使用してキャッチする必要があります。あなたはconstでそれを修飾するかもしれません。

std::runtime_errorを投げた場合は、std::runtime_error const &、またはその基本クラスstd::exception const &を使用してキャッチできます。

それでは、何が良いですか?それについての良い

はあなたが最終的に std::exceptionから派生したクラスを使用して例外をスローした場合に例外をスローするために使用され、その後、あなたは関係なく which derived classstd::exception const&として例外を受け入れるだけONE catchブロックを、書くことができるということです。ここで

は一例です:

void f(A & a) 
{ 
    if (!check_arg(a)) 
    { 
      throw std::invalid_argument("invalid argument"); 
    } 
    else if (!check_size(a)) 
    { 
      throw std::length_error("invalid length");    
    } 

    //code 
    if(someCondition) 
    { 
      //assume your_own_defined_exception's ultimate base is std::exception 
      throw your_own_defined_exception("condition unsatisfied");       
    } 
    //... 

} 

は今興味深い部分:

try 
{ 
     f(a); //it can throw exception of at least 3 types! 
} 
catch(std::exception const &e) //all types can be caught by just one catch! 
{ 
    //handle this case 
} 

良いf()が投げる可能性という理由だけで、あなたがcatchブロックを書くためにを要求されないということです3つの異なるタイプの例外。 catchを書いて、それが何らかの方法であなたに利益をもたらすならば、それらを別々に扱うことができます。しかしここに留意すべきポイントは:ではなく、の要件です!

つまり、クラス階層を利用できます。

+0

したがって、基本的に継承によってエラー処理の設計が簡単になります。かなりエレガント。自分の例外クラスを定義してそのようにすれば、私は同じ結果を生み出すことができます、はい? –

+3

@StevenLu独自の例外クラスを派生した場合は、ホイールを再作成し、std :: exceptionを捕捉することに依存するコードを破損する可能性があります。これはあなたの個人的なプロジェクトにとってはうまくいくかもしれませんが、あなたのコードを他の人に配布することは困難です。標準的なアプローチは、 'std :: exception'をサブクラス化するアプリケーション固有の例外階層を持たせることです。たとえば、すべての例外を 'Std :: exception'のサブクラスである' StevenLuException'のサブクラスにすることができます。 – sfstewman

+0

@StevenLu:あなたの例外クラスが最終的に 'std :: exception'から派生する場合は、それは優雅なデザインです。私の例のコードでは 'your_own_defined_exception'と呼ばれる* 3番目の例外を参照してください。私は最終的に 'std :: exception'から派生しなければならないと言いました。 – Nawaz

1

主にあなたが他の人と仕事をしている場合、何を捕まえるかについて同意する必要があるからです。もし私がキャッチしてconst std::exception&を投げてconst char*を投げれば、私はあなたのものを捕まえるつもりはなく、悪いことが起こる可能性があります。

誰もがそれに固執している限り、どんなタイプがスローされ捕まえられるかは実際問題ではありません。私はstd::exceptionconst char*より選択されていると思います。例外オブジェクトに単なる文字列以上のものを置くことができるからです。それはもっと柔軟です。

2

std :: exceptionから派生した例外だけをスローするようにコード内でルールを作成すると、それらをキャッチする方が簡単です。

catch (std::exception& e) 
{ 
    log_message(e); 
    throw; 
} 

をしかし、あなたは、この規則に従わない場合、あなたは、あなたがする必要がないときcatch句を記述することに終わる:他の言葉であなただけのstd ::例外で、単一のcatch節を持つことができます。あなたはintまたは文字列を投げると、あなたがすることはできません特定のエラーをキャッチしたい場合

- 彼他の回答から

+0

あなたは本当に何かがある場合(そしてC++では、RAIIで、これは十分に稀でなければならない)、それを「飲み込む」ためには、すべてのレイヤーで捕捉して再獲得することはほとんどありません。 –

+0

期待されていない例外のスタックトレースを生成すると便利です。これは、エラーを診断し、どこから例外が検出されたかを追跡するのに役立ちます。 – sashang

+0

スタックは便利だと私は同意しますが、あなたのアプローチには2つの欠点があります。最初にコードが乱雑になっていますが、例外の場合に*特定の*アクションをとるべきときはもはや明らかになりません。それはgccやClangなどの一般的なコンパイラで使用されるゼロコスト例外の実装がスローに対して厳しいペナルティを課すためです。他にも、より良い選択肢があります。スローの時点でスタックをキャプチャするためのプラットフォーム固有のコードは1です。別の方法は、解読中に例外に追加される「注釈」を記録するためにRAIIを使用することです。 –

1

1つの追加のポイントはこれです。 すべての "int"例外をキャッチして、キャッチしたいものを比較してから、対処する準備ができていないものを再スローする必要があります。例外から継承する場合は、処理したい特定の例外をキャッチして、それらをすべて処理したい場合はstd :: exceptionを捕捉できるという利点があります。

関連する問題