これら 3 つすべてに対処するには、.NET から派生した独自のカスタム例外をスローするのが最善であることがわかりました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 があったかどうかを (おそらくダイアログなどで) 知ることができる明示的なリターン コードが必要です。
try-catch
C++ 例外処理の一部は、スタックをブロックまでアンワインドすることであることに注意してください。つまり、プログラムで起こっていることを中止し、スタックをクリーンアップします。私の DVD の例のようなものの場合、スタックの多くを巻き戻したくはないはずです。それは壊滅的ではありませんでした。ユーザーに知らせてから、もう一度試してもらう必要があります。
しかし、繰り返しになりますが、これは経験と私の読書に基づいて、C++ 例外を使用する私の好みの方法です。そうでなければ、私は意見を受け入れます。
編集:コメンターのアドバイスに基づいて変更std::exception
されました。std::runtime_error