我对dynamic_cast如何将数组的元素强制转换为更大的类感到好奇(它会将所有其他元素都移位了吗?)。所以我写了一个小代码来尝试。但是我很惊讶,因为它在第一行只是编译而出现段错误。为什么呢

#include <iostream>

class A
{
public:
    virtual ~A() {}
};

class B : public A
{
public:
    int x;
};

class C : public A
{
public:
    int x;
    int y;
};

int main()
{
    A* aArray = new B[2];
    (dynamic_cast<B&>(aArray[0])).x = 1; //segfault here
    (dynamic_cast<B&>(aArray[1])).x = 2;

    (dynamic_cast<C&>(aArray[0])).y = 3;

    std::cout << (dynamic_cast<B&>(aArray[1])).x << std::endl;

    return 0;
}

最佳答案

我来啦。我编译并运行了gdb

首先,我设置打印对象选项:

(gdb) set print object

检查一个数组的地址
(gdb) print aArray
$1 = (B *) 0x8003a404

检查A和B的大小
(gdb) print sizeof(B)
$2 = 8
(gdb) print sizeof(A)
$3 = 4

获取aArray的地址[0]
(gdb) print &aArray[0]
$4 = (B *) 0x8003a404

获取aArray的地址[1]
(gdb) print &aArray[1]
$5 = (A *) 0x8003a408

引用answer in linked question:







在这种特定情况下,指针算法的实现是通过指针类型的大小来增加指针内存(但请引用此answer以获取更多细微差别)。
aArray + 1的作用是指向类型A的对象数组的第二个元素

符合:
(gdb) print (A*)(((char *)aArray) + sizeof(A))
$6 = (A *) 0x8003a408

...但是aArray实际上是B型对象的数组。

因此,数组的第二个元素是:
(gdb) print &((B *)aArray)[1]
$6 = (B *) 0x8003a40c

因此您最终指向第一个B对象中间的某处...而该访问导致了分段错误。

有关替代说明的示例,请参见:[http://www.parashift.com/c++-faq/array-derived-vs-base.html]

关于c++ - 启用了RTTI的dynamic_cast segfault,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24187390/

10-13 07:32