2012-04-28 16 views
3

先ほどのインスタンスでは、基本型へのポインタを取る関数がありました。この型は、いくつかの追加機能にアクセスするために派生型にアップキャストする必要がありました。しかし、dynamic_castが失敗しました。私の型は基本型を間違いなく継承していたので、これは奇妙でした。 スタックオブジェクトの動的キャストが失敗しました

は何が起こっていたかの底に取得するには、私は私が見ていたものを複製考えて、次のテストプログラムを作成:あなただけを提示された場合ので、面白いです

void cast(TestClass *baseType) 
{ 
    if (dynamic_cast<Derived *>(baseType)) 
     TRACE("cast was sucessful"); 
    else 
     TRACE("cast failed"); 
} 

int main(int argc, char *argv[]) 
{ 
    Derived *test1 = new Derived(); 
    TestClass *test2 = new TestClass(); 
    TestClass test3; 

    test1->identify(); // prints: this is a Derived class 
    test2->identify(); // prints: this is a TestClass 

    cast(test1); // succesful 
    cast(test2); // fail - expected 

    // reassign test2 to test1 
    test2 = test1; 
    test2->identify(); // prints: this is a Derived class 

    cast(test2); // succesful 

    // the interesting part, the test3 object (created on stack), does not cast 
    // despite that it would seem possible from the cast method. 
    test3 = *test1; 
    test3.identify(); // prints: this is a TestClass 
    cast(&test3); // fails? 

    return a.exec(); 
} 

メソッドcast()を呼び出すと、渡されたオブジェクトをキャストすることが可能になることが期待されます。これが当てはまらないことを実証しました。オブジェクトが元々どのように作成されたかによって異なります。紛らわしいのは、値ではなく参照によって再割り当てされたオブジェクトをキャストすることが可能な理由です。さらに、static_castの作品を使用していますが、タイプが保証されている限り、互換性はありますか?

答えて

7

test3は、タイプTestClassです(これはDerivedの親であると見なします)。したがって、動的キャストは失敗します。

*test1を割り当てても、割り当てはTestClass部分(別名slicing)のみをコピーします。ポインターにポインターを割り当てると、スライスが発生しません。あなたはそのベースの一部を持つものとして派生したオブジェクトと考えることができ

:あなたはポインタ(test2=test1)を割り当てると

*test1: 
|--------------| 
|TestClass part| 
|--------------| 
|Derived part | 
|--------------| 

test3: 
|--------------| 
|TestClass part| 
|--------------| 

、オブジェクト自体は変更されません、あなただけの別の経由でそれを見ていますガラス(TestClassへのポインタを介して)、鋳造作業。

あなたがオブジェクト自体(test3=*test1)を割り当てると、送信先(test3が)だけTestClassオブジェクトのための部屋を持っているので、コピーは余分Derived一部を奪います。

+0

非常に明確な答えです。ありがとう。インスタンスがスライスされると、派生型を '回復'する方法はありません。 – user975326

+0

@ user975326 - 正しい。型の代わりに参照を使用することができ、この点に関してはポインタのように動作しますが、構文はスタックに割り当てられたオブジェクトを扱っている場合と同じです。 – Attila

関連する問題