2011-01-03 14 views
23

C++では、オブジェクトの実際の型が同じクラスであるか、同じクラスでないか、派生型であるかどうかを知りたいと思います。これは、次のC#コードに似ています。C++での型チェック

Class Base 
{ 
} 

Class Child:Base 
{ 
} 

Base childObject = new Child(); 

If (childObject.GetType() == typeof(Child)) 
{ 
// do some code 
} 

ありがとう!

+0

'childObject'のタイプは何ですか?実行時に型の概念が存在しないため、C++でこれを行う一般的な方法はありません。 –

+0

質問: – Homam

+2

質問を編集しますが、childObject.GetType()が何であるかについては何も述べていませんが、このコードは型の比較で分岐するのでひどいです。それがOOPが排除しなければならないものです。 –

答えて

48

これには2通りの方法があります。まず、typeid演算子を使用できます。この演算子は、オブジェクトのタイプに関する情報を含むtype_info構造体を返します。例:あなたがここにtypeid(*ptr)ないtypeid(ptr)を使用する必要が

Base* ptr = /* ... */ 
if (typeid(*ptr) == typeid(DerivedType)) { 
    /* ... ptr points to a DerivedType ... */ 
} 

注意してください。 typeid(ptr)を使用している場合、Base*のオブジェクトはBase*のオブジェクトになります。ポインターは、ポインターの種類にかかわらずタイプがBase*なので、オブジェクトが返されます。注意すべき

重要な点は何ptrポイントでは正確DerivedTypeとしてであれば、これはチェックすることです。 ptrDerivedType(おそらくEvenMoreDerivedType)から派生した型のオブジェクトを指している場合、このコードは正しく動作しません。

もう少し頑強な種類のオブジェクトを指しているかどうかを確認する別の方法は、dynamic_cast演算子を使用することです。 dynamic_castは、実行時にキャストが成功すると有効なポインタを返すチェックされた型キャストを実行し、そうでない場合はNULLを返します。たとえば、次のように

Base* ptr = /* ... */; 
DerivedType* derived = dynamic_cast<DerivedType*>(ptr); 
if (derived) { 
    /* ... points to a DerivedType ... */ 
} 

これは追加の利点を持っているEvenMoreDerivedTypeのようなものでptrがポイント場合、キャストはまだDerivedTypeからEvenMoreDerivedType継承するため、成功すること。

最終的な思考として、あなたは時々、このようなコードを参照してください:

Base* ptr = /* ... */ 
if (DerivedType* derived = dynamic_cast<DerivedType*>(ptr)) { 
    /* ... points to a DerivedType ... */ 
} 

これはif文の本体へderivedポインタをローカル・スコープと非ゼロ値はC++でtrueに評価されているという事実を使用しています。私は個人的にはこれを読みやすく、エラーを起こしにくいが、忘れてはならないことは、あなたにとって最も簡単なものとなる。

希望すると便利です。

+0

彼はオブジェクトが派生クラスの場合ではなく、ベースであるかどうかを知りたがっています。 – Puppy

+0

ああ...私は、ポインタが子タイプを指していたかどうかをチェックしていた彼のサンプルコードによって混乱しました。有効なポイント。 – templatetypedef

2

typeid()を使用できます。

if (typeid(childObject) == typeid(ChildType)) { 
} 

これがtrueを返す場合は、それが子クラスであることがわかります。

+2

ランタイムタイプID(RTTI)も有効にしてコンパイルする必要があります。 –

+3

この**は、比較されるアイテムにvtblがある場合にのみ**機能します。 –

+0

@Billy:それは本当ですが、基本クラスに仮想デストラクタを与えないのは誰ですか?仮想関数は事実上継承のポイントです。それを期待するのは不合理ではない。 – Puppy

9

DeadMGの答えは正しいです(私は何度もタイプIDを使用しました)が、私は後世のためにこれを投げ捨てると思いました。これを行うための「正しい」方法は、オブジェクト指向のビューです。

Class Base 
{ 
    virtual void something() { 
     // probably a no-op, but maybe some default stuff 
    } 
} 

Class Child : public Base 
{ 
    virtual void something() { 
     // do your child-specific code here 
    } 
} 

Base* childObject = new Child(); 
childObject->something(); // does the right thing 
+0

私はこの答えを秒です。 DeadMGの答えは正しいが、良いプログラミングの練習ではないかもしれない..! –

+0

これは、オブジェクトの内部を何かしたいときにうまくいきます。一方、型に応じてオブジェクトを処理したい場合は、複雑で不便になります(二重のディスパッチと訪問者すべて) –

+0

@ 7vies、しかし、この仮想メソッドのアプローチが最も効果的です維持するのが最も簡単です。 dynamic_castまたはtypeidが適切なアプローチである場合がありますが、それはまれなケースです。 – Tim