2012-04-25 8 views
4

誰かが、うまく設計された堅牢な例外メカニズムを備えたオープンソースのC++アプリケーションを知っていますか?私が見るほとんどのコード/例は疑わしいものです:よく設計された例外メカニズムを持つC++プロジェクト

  1. メッセージ文字列を引数としてオブジェクトを投げます。例外を致命的とマークしているので間違っていると思われます。ユーザーに表示できるエラーメッセージは、例外を処理しようとするクライアントコードの余裕がほとんどありません。例外が致命的であっても、難しいロケール(言語)のようなものは、スローの時点でメッセージをフォーマットすることが私にとっては悪い考えです。
  2. 基本例外クラスから派生したさまざまな例外クラスを使用します。間違ったこと(ファイルを開く、ファイルを読み込む、ファイルを書き込む、スレッドを作成する、など)を行うたびに、新しいクラス/タイプを導入するのは間違っています。基本型を使用して最高レベルのすべての未処理の例外をキャッチすると、意味のあるエラーメッセージを表示するために必要な型情報が失われます。
  3. すべてのコンポーネント/ライブラリに対して基本例外クラスから派生した1つの例外クラスを使用し、エラーコードを引数として指定して、正確なエラーを示します。基底型でキャッチすると、あいまいさが発生します。 (誰のエラーコード "3"を捕まえたのですか?)

正しい方向のいくつかのポインタを歓迎します。

+0

私が見た最も単純なC++例外メカニズムは、Symbianの取り組みです。すべてがint型であり、例外クラスもメッセージもありません。 'Leave'は例外と同義です:http://www.developer.nokia.com/Community/Wiki/Using_TRAP – James

+1

(1)例外文字列は、ユーザではなくプログラマ向けです。そこにロケールを使用しないでください。 (2)どのようにコンパイラが解き放つべき正しい場所を決めることができましたか? (3)それは明らかにエラーコードの問題です。それをしないでください。 –

+0

@James:シンプルでは必ずしも良いとは限りません。その場合、私はそれを悪いと呼ぶだろう。 –

答えて

4

これらの3つすべてに対処するために、私にとっては、std::runtime_errorから派生した独自のカスタム例外をスローすることがわかりました。このように:それは私が常に次の形式のようなものに入れた文字列を、受け入れることができます

#include <exception> 

class ChrisAException : public std::runtime_error 
{ 
     /// constructor only which passes message to base class 
     ChrisAException(std::string msg) 
     : std::runtime_error(msg) 
     { 

     } 
} 

(負xが有効な入力ではなかったと仮定して、それを呼び出して何かを意味するとエラーにあった):

#include "ChrisAException.h" 

void myfunction(int x) 
{ 

    if(x < 0) 
    { 
     throw ChrisAException("myfunction(): input was negative!"); 
    } 

    // rest of your function 
} 

この例外では、これらの例外の文字列はエンドユーザーよりプログラマの方が多いことに注意してください。失敗したときにロケールで何か意味のあるものを表示するのは、インターフェースの仕事のプログラマーです。例外の文字列は、ログインまたはデバッグ時に見ることができますいずれか

あなたは最終的にそれをキャッチすることができますこの方法(好ましく!):私は個人的に例外があまりにも多くの種類を導出好きではない

try 
{ 
     // high level code ultimately calling myfunction 

} 
catch(ChrisAException &cae) 
{ 
     // then log cae.what() 
} 
catch(std::runtime_error &e) 
{ 
     // this will also catch ChrisAException's if the above block wasn't there 
} 
catch(...) 
{ 
     // caught something unknown 
} 

、またはエラーコードを与えることができます。私は文字列メッセージに報告をさせます。

通常、私はC++の例外を使用して、「プログラムに何か問題があった」ことを意味し、ではなく、通常の使用事例を処理するためにを処理します。したがって、私の場合、アルゴリズムの実行中にスローされた例外は、「何かが間違っていることをユーザーに知らせる」または「ユーザーに知らせない」(コードがどれほど重要であったかに応じて)プログラマーになにか知らせるようにしてください。

私は、基本的にプログラミングエラーではないケース、例えば何らかの誤ったロジックや何かが間違っているなど、C++例外を使用しません。たとえば、DVD書き込みプログラムのドライブに空のDVDがないなど、通常のプログラム状況を処理するためにC++の例外は使用しません。そのためには、空のDVDがあるかどうかをユーザーが(多分ダイアログなどで)知ることができるようにする明示的なリターンコードが必要です。

C++例外処理の一部は、ブロックtry-catch。私にとっては、プログラムで何が起こっているのかを中止し、スタックをクリーンアップすることを意味します。私のDVDの例のようなものの場合、実際にスタックの多くを巻き戻したくないはずです。それは破滅的ではなかった。ユーザーに知らせてからもう一度試してみましょう。

これは、経験と読書に基づいて、C++の例外を使用するのに好ましい方法です。私はそうでなければ意見に開放されています。

編集:変更されたstd::exceptionstd::runtime_errorコメント投稿者のアドバイスに基づいて。

+0

最高レベルのキャッシングコードが例外の種類を決定して、それを処理しようとするか、またはユーザーにエラーメッセージを出力する方法を教えてください。どの文字列を比較しますか? – Unimportant

+0

これを説明するために投稿を編集しました。 –

+3

'std :: exception'には文字列を取るコンストラクタはなく、MSVCの(準拠しない)実装でのみ使用されます。非常に重要ではありませんが、それでもなお重要です。この点で標準に準拠するコンパイラでは、代わりに 'std :: runtime_error'を使うことができます。 –

関連する問題