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部分(又名slicing)。当您将指针分配给指针时,不会发生切片。

您可以将派生对象视为具有其基础的一部分:

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

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

当您分配指针 ( test2=test1) 时,对象本身不会改变,您只是通过不同的玻璃(通过指向 的指针TestClass)查看它,因此可以进行投射。

当您分配对象本身 ( test3=*test1) 时,目标 ( test3) 仅具有放置TestClass对象的空间,因此副本会带走多余的Derived部分。

于 2012-04-28T16:13:22.703 回答