其他分享
首页 > 其他分享> > c – 堆栈对象的动态转换失败

c – 堆栈对象的动态转换失败

作者:互联网

前几天我遇到了一个实例,我有一个函数,它指向一个基类型,然后我需要向上转换为派生类型以访问一些额外的功能.但是,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工作吗?

解决方法:

test3是TestClass类型(我假设它是Derived的父级),因此动态转换失败.

即使您为其分配* test1,分配也只复制TestClass部分(也称为slicing).为指针指定指针时,不会发生切片.

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

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

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

当你指定一个指针(test2 = test1)时,对象本身不会改变,你只是通过一个不同的玻璃(通过一个指向TestClass的指针)来看它,这样就可以进行投射.

当您指定一个对象本身(test3 = * test1)时,目标(test3)只有一个TestClass对象的空间,因此该副本将带走额外的Derived部分.

标签:dynamic-cast,object-slicing,c,reference
来源: https://codeday.me/bug/20190729/1573423.html