有许多问题与此问题非常类似,区别在于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
实例,因为大小相等,但代码是否仍然正确?
答案 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的对象时,存在数据损坏的可能性。