与多态性一起使用的数组的奇怪输出

Me *_*d I 1 c++ arrays

可能重复:
指向基址的指针可以指向派生对象数组吗?

我正在练习学到的东西,我尝试了下面的内容:

#include <iostream>

struct S {
    S() : val(0) {}

    int val;
};

struct D : S {
    D() : val(1) {}

    int val;
};

void f(S *s) {
    for (int i = 0; i < 5; i++, s++)
        std::cout << s->val;
}

int main() {
    D d[5];
    f(d);
}
Run Code Online (Sandbox Code Playgroud)

我觉得奇怪的是输出01010不是11111我想象的那样.所以它似乎是val从S类中获取成员而不是D每个其他循环上的类.但为什么?

Bra*_*vic 6

由于s++通过增量指针sizeof(S),而不是sizeof(D),但s实际上指向的数组D在运行时.

  • 第一次迭代恰好与S::val第一个数组元素(0)对齐,
  • 第二个元素与D::val第一个元素(即1),
  • S::val第二个元素的第三个元素(即0)
  • 等等...

这实际上是一种未定义的行为.如果您的类看起来不同(或使用了具有不同对齐的平台),您将收到不同甚至更令人困惑的结果.

如果你不需要多态,只需声明函数接收一个D(不是S)数组.如果确实需要多态性,则应考虑使用(智能)指针数组,而不是具体元素数组(并通过虚函数而不是直接字段访问来访问数据).