私は2つの異なる使用モデルを持つC++クラスを書いています。1つは外部であり、ユーザーが例外を発生させたくないと想定しています。代わりに、エラーコードが返されます。もう1つの使用方法は内部的なもので、面倒なエラーコードのチェックを避け、例外を処理することを好みます。
2つのアプローチを組み合わせる良い方法は何でしょうか?
編集:
- 両方のアプローチを同じバイナリで使用できます
- 明示的は暗黙的よりも優れています
- 特別な構成をユーザーに公開することは避けてください。
他の理由で2つのクラスを作成できない場合を除いて、私はMarkRansomの答えが私のものよりも好きです。
別の方法として、すべての関数がint * pRet=NULLなどのデフォルトのfinal引数を持つようにインターフェイスを作成できます。pRet == NULLの場合、例外を使用することを示します。pRet!= NULLの場合、呼び出し元は、関数の最後にエラーコードで更新する必要があるポインターを渡しました。
関数の内部では、例外をキャッチしてから、それらを飲み込むか、pRet引数に基づいて再スローする必要があります。
クラスの2つのバージョンを作成します。1つはスローし、もう1つはエラーコードを返します。これらは両方とも、コードの大部分を含む共通ベースから派生できます。
そのようなことを試したことはありませんが、これが私がすることです。
エラータイプ:
extern const bool exceptionmode;
enum error_codes {no_error, whatever};
struct error_type {
error_codes id;
//maybe also a non-owning const char* message?
error_type() :id(no_error) {}
error_type(error_codes code) :id(code)
{
if (exceptionmode) throw_as_exception();
}
const char* get_as_string() {
switch(id) {
case whatever: return "out of bounds exception";
case no_error: return "no error";
default: return "unknown exception";
}
}
void throw_as_exception() {
switch(id) {
case whatever: throw std::out_of_bounds("out of bounds exception");
case no_error: break; //no error
default: throw std::exception("unknown exception");
}
}
};
クラスと関数:
class myclass {
public:
error_type my_member_function() {
//stuff
if (condition)
return whatever;
//more stuff
return no_error;
}
};
あなたが本当に勇気があるなら、error_typeクラスが比較されたり、変換されたり、チェックされたりしない場合にassertするようにして、誰もが戻り値をチェックすることを忘れないようにすることができます。