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