プログラムコンポーネントの例外クラスの階層を設計する際に問題が発生しました。 このコンポーネントには、いくつかの障害ケース(たとえば、std::bad_alloc
、std::invalid_argument
、など)があり、非常に具体的な障害ケースごとに、上記の一般的な例外カテゴリから派生した対応する例外クラスを作成しました。例外クラスの多重継承
ここでは、すべての例外クラスを単一のクラス(例:Base
)から派生させるように要求されました。クライアントは、失敗が自分のコンポーネントかどうかを知るために、Base
をキャッチします。しかし、私のコンポーネントの別のクライアントが、例外が発生した場所には関心がありませんが、なぜそれが発生したのかについては興味がありません。したがって、私の例外クラスは、一般的な標準例外クラスだけでなく、単一の区別された基本クラスBase
の両方から派生しなければならないようです。
私の質問は:Base
をstd::exception
から派生させるべきですか?
std :: exceptionから派生している場合は、標準例外クラスが仮想継承を使用していないように見えるため、各例外クラス内に2つのstd :: exceptionインスタンスが存在する必要があります。私はこのケースでは例外クラスごとに変換演算子をstd::exception
に書く必要があり、それは非常に退屈なようです。
std :: exceptionから派生していない場合、Base
を捕捉したいクライアントは、基本クラス内に実装しない限り、std :: exceptionの能力を使用できません。たとえばwhat()
です。そうであれば、すべての例外クラスは本質的に1つの能力のために2つの名前を持ちますが、それはばかげているようです。また、クライアントがstd::exception
から派生した例外クラスを期待している他の人にそれを戻すことを望む場合、クライアントは何らかの形で再パックする必要がありますが、これは非常に望ましくありません。
どうすればよいですか?
編集: 2番目のクライアントの要求は、彼/彼女が使用している非常に多くのコンポーネントがあるので、彼/彼女は同時に、あまりにも投げて、むしろ私が作ったものよりも、標準の例外クラスを使用したいということです多くの種類の例外があるので、すべての失敗事例を認識できません。
はい私は 'std :: exception'から派生することができますが、私が質問したように、' std :: exception'の2つのインスタンスがあるので、 'std :: exception'への変換はあいまいになります。仮想継承は役に立たない。 'std :: logic_error'はそれを使用しません。 –
いいえ - あなたが仮想的に継承している場合、唯一のものがあります。これは、敢えてダイヤモンドの問題に対する解決策と呼ばれています。 – lorro
それはすべての基本クラスが実質的にグランドベースクラスを継承する場合にのみ起こりますね。私の場合、 'Base'は仮想継承を使用できますが、' std :: logic_error'はそれを使用しません。 –