私の意見では、「約束」を守ることができない場合、または「契約」を破る必要がある場合、関数は例外をスローする必要があります。関数の署名 (名前とパラメーター) によって、そのコントラクトが決まります。
次の 2 つのメンバー関数が与えられた場合:
const Apple* FindApple(const wchar_t* name) const;
const Apple& GetApple(const wchar_t* name) const;
これらの関数の名前とその戻り値は、FindAppleの場合、関数が正しいリンゴが見つからなかった場合に NULL を完全に返すことができることを示していますが、 GetAppleの場合は、リンゴが返されることを期待しています。 . その 2 番目の関数がその約束を守れない場合、例外をスローする必要があります。
例外は、関数がこれらの状態を報告する他の方法がない例外的な状態を意味します。それを約束の一部にすることにした場合(読み取り:関数シグネチャ)、例外をスローせずにその状態を報告できます。
FindAppleの場合、「適切なリンゴが見つからない」という状態をどのように処理するかは、呼び出し元が決定することに注意してください。これは、もはや例外的な状態ではないためです。
すべての例外を回避しようとするかもしれませんが、それは、考えられるすべての例外条件を考慮する必要があり、代わりに呼び出し元に負担をかけることを意味します。次に、呼び出し元は「エラー状態」をチェックする必要があります。
最終的に、例外を処理する必要がありますが、特定の条件を有効な方法で処理する方法を知っている呼び出し元だけが例外を処理する必要があります。そして、これは可能な限り広い解釈で意味します。あきらめたサービスは後で再試行します、役立つエラーメッセージを提供する UI、「おっと」画面を表示するがうまく回復する Web アプリなど...などです。 .
デイブ