1

重複の可能性:
ベースへのポインターは、派生オブジェクトの配列を指すことができますか?

私は学んだことを練習していて、次のことを試しました。

#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);
}

私が奇妙だと思うのは、出力が私が期待したもの01010ではないということです。11111したがって、他のすべてのループのクラスではなくval、クラスからメンバーを取得しているようです。しかし、なぜ?SD

4

1 に答える 1

6

ポインタをではなく、だけs++インクリメントするため、実際には実行時にの配列を指します。sizeof(S)sizeof(D)sD

  • 最初の反復は、たまたまS::val最初の配列要素(0)と整列されます。
  • 最初の要素(1)D::valの2番目のwith 、
  • S::val2番目の要素(0)の3番目
  • 等々...

これは本質的に未定義の動作です。クラスの外観が異なる場合(または異なる配置のプラットフォームが使用された場合)、異なる、さらに厄介な結果が得られます。

ポリモーフィズムが必要ない場合は、D(ではなくS)の配列を受け取る関数を宣言するだけです。ポリモーフィズムが必要な場合は、具体的な要素の配列ではなく、(スマート)ポインターの配列を使用することを検討する必要があります(直接フィールドアクセスではなく、仮想関数を介してデータにアクセスします)。

于 2013-01-25T18:03:23.403 に答える