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タイプに互換性があることが保証されている限り、作業を使用しますか?

4

1 に答える 1

7

test3はタイプTestClass(Derivedの親であると思います)であるため、動的キャストは失敗します。

割り当て*test1ても、割り当てはパーツのみをコピーしますTestClass(別名スライス)。ポインタをポインタに割り当てると、スライスは発生しません。

派生オブジェクトは、そのベースの一部を持っていると考えることができます。

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

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

ポインタ()を割り当てるtest2=test1と、オブジェクト自体は変更されません。別のガラスを介して(へのポインタを介して)オブジェクトを表示するだけなTestClassので、キャストが機能します。

オブジェクト自体(test3=*test1)を割り当てると、宛先(test3)にはオブジェクト用のスペースしかないTestClassため、コピーによって余分なDerived部分が削除されます。

于 2012-04-28T16:13:22.703 に答える