dynamic_cast のエラー処理に関連する適切な方法はありますか (必要がない場合は使用しないことを除く)。NULL と bad_cast をスローする方法を考えています。両方をチェックする必要がありますか?そして、bad_cast をキャッチしたり NULL を検出したりした場合、おそらくとにかく回復できません... 今のところ、assert を使用して、dynamic_cast が NULL 値ではない値を返したかどうかを確認しています。コードレビューでこの解決策を受け入れますか?
5 に答える
dynamic_cast
が成功する場合は、boost::polymorphic_downcast
代わりに を使用することをお勧めします。これは次のようになります。
assert(dynamic_cast<T*>(o) == static_cast<T*>(o));
return static_cast<T*>(o);
このようにして、デバッグ ビルドでエラーを検出すると同時に、リリース ビルドでの実行時のオーバーヘッドを回避します。
キャストが失敗する可能性があり、それを検出したい場合はdynamic_cast
、参照型を使用してキャストします。このキャストは、エラーの場合にスローbad_cast
され、プログラムを停止します。(あなたが言うように、とにかく回復しない場合、これは良いことです)
T& t = dynamic_cast<T&>(o);
t.func(); //< Use t here, no extra check required
dynamic_cast
コンテキストで 0 ポインターが意味を持つ場合にのみ、ポインター型に使用します。if
次のように使用することをお勧めします。
if (T* t = dynamic_cast<T*>(o)) {
t->func(); //< Use t here, it is valid
}
// consider having an else-clause
この最後のオプションでは、dynamic_cast
が 0 を返す場合に実行パスが適切であることを確認する必要があります。
あなたの質問に直接答えるには:私が与えた最初の2つの選択肢のうちの1つをassert
、コードに明示的に含めることをお勧めします:)
bad_cast は、参照をキャストするときにのみスローされます
dynamic_cast< Derived & >(baseclass)
ポインターをキャストすると NULL が返される
dynamic_cast< Derived * >(&baseclass)
したがって、両方をチェックする必要はありません。
アサートは許容できますが、それはコンテキストに大きく依存します。繰り返しますが、ほとんどすべてのアサートに当てはまります...
はいといいえ。
boost::polymorphic_downcast<>
dynamic_cast<>
デバッグ段階でのエラーを処理するには、確かに良いオプションです。ただし、コンパイル時に渡されるポリモーフィック型を予測できるpolymorphic_downcast<>
場合にのみ使用する必要があります。それ以外の場合は、代わりに を使用する必要があります。dynamic_cast<>
ただし、次のシーケンス:
if (T1* t1 = dynamic_cast<T1*>(o))
{ }
if (T2* t2 = dynamic_cast<T2*>(o))
{ }
if (T3* t3 = dynamic_cast<T3*>(o))
{ }
ポリモーフィズムと仮想関数によって解決する必要がある非常に悪い設計を示します。
場合によります... ;-)
dynamic_cast
たとえば、私以外の誰も基本クラスへのポインターのコンテナーにポリモーフィック型を追加しなかった場合など、 が何か使用可能なものを提供することを本当に期待している場合は、参照キャストを使用しstd::bad_cast
て、アプリケーションを強制終了させます。他にやるべきことはあまりありません。
ただし、必ずしも実装する必要のないインターフェイスによって公開される何らかの機能についてポリモーフィック型をクエリしている場合は、ポインターキャストを使用し、NULL はエラーにはなりません (ただし、もちろん、私はその機能が本当にそこにあることを期待していました-しかし、最初に参照キャストを求めていました...)
「場合による」という回答に同意し、「グレースフルな劣化」も追加します。キャストがどこかで失敗したからといって、アプリケーションを失敗させる十分な理由にはなりません (そして、ユーザーは自分の作業を失うなど)。アサートと防御的プログラミングの組み合わせをお勧めします。
ptr = dynamic_cast<MyClass>(obj);
ASSERT(ptr);
if(ptr)
{
// do stuff
}