派生对象数组到基础对象数组

时间:2014-10-23 12:20:28

标签: c++ arrays pointers

有许多问题与此问题非常类似,区别在于sizeof(Base) != sizeof(Derived)。由于显而易见的原因,它不会起作用(应用于指针的下标运算符与指针大小相关,而不是与实际的异步类型相关)。但是,我想知道这段代码是否正确:

struct Base
{
    int Data;
};
struct Derived : public Base
{
};
int main()
{
    static_assert(sizeof(Base) == sizeof(Derived), "Sizes are not equal");

    Derived Data[10];
    Base* Ptr = Data;
    Ptr[3].Data = 5;
}

显然,Ptr[3]不再访问任何半翻录的Base实例,因为大小相等,但代码是否仍然正确?

4 个答案:

答案 0 :(得分:1)

假设我们有一个接收Derived

的函数
double foo(Derived d);

现在考虑一下代码的轻微变化:

Derived Data[10];
Base* Ptr = Data;
Base myB;
Ptr[3] = myB;

基本上我们已将Base对象放入Data数组中。然后我们打电话给

foo(Data[3]);

瞧,我们已经欺骗foo接收Base

这就是你不应该将Derived数组视为Base数组的原因。这不仅仅是尺寸问题。

答案 1 :(得分:1)

是的,这是正确的(在明确定义的意义上,不一定是理智的),因为这两个类是布局兼容的 - 它们是具有相同非静态数据的标准布局结构成员。

但是,它非常脆弱;对类的小改动可能会破坏兼容性并给出未定义的行为。

答案 2 :(得分:0)

让我们考虑以下几行:

Derived Data[10];
Base* Ptr = Data;

Data包含数组第一个元素的地址。所以,它是Derived*类型的指针。 有Derived*Base*的静态广播。这意味着代码是正确的。

答案 3 :(得分:0)

这是正确的,但一般不会这样做,因为当派生类的指针指向base的对象时,存在数据损坏的可能性。

相关问题