web-dev-qa-db-ja.com

C ++での型チェック

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

Class Base
{
}

Class Child:Base
{
}

Base childObject = new Child();

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

ありがとう!

30
Homam

これを行うには2つの方法があります。まず、typeid演算子を使用できます。この演算子は、オブジェクトのタイプに関する情報を含むtype_info構造体を返します。例えば:

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

ここではtypeid(*ptr)ではなくtypeid(ptr)を使用する必要があることに注意してください。 typeid(ptr)を使用する場合、ポインターはtype_infoBase*オブジェクトを取得します。これは、ポインターが何を指しているかに関係なくBase*型を持っているためです。

注意すべき重要な点は、これはptrが指しているものがexactly as DerivedTypeであるかどうかをチェックすることです。 ptrDerivedTypeから派生したタイプのオブジェクト(多分EvenMoreDerivedType)を指している場合、このコードは正しく機能しません。

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

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

これには、ptrEvenMoreDerivedTypeを継承するため、EvenMoreDerivedTypeDerivedTypeのようなものを指す場合でも、キャストが成功するという追加の利点があります。

最後に、次のようなコードが表示されることがあります。

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

これは、derivedポインターをifステートメントの本体にローカルでスコープし、C++ではゼロ以外の値がtrueに評価されるという事実を使用します。私は個人的にこれが読みやすく、エラーが発生しにくいと思いますが、必ずあなたにとって最も簡単な方法で行ってください。

お役に立てれば!

56
templatetypedef

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

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
11
Tim

Typeid()を使用できます。

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

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

2
Puppy