1

Possible Duplicate:
Can a pointer to base point to an array of derived objects?

I am practicing what learned and I tried the folowing:

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

What I find weird is that the output is 01010 instead of 11111 like I expected. So it seems to be getting the val member from the S class instead of the D class on every other loop. But why?

Community
  • 1
  • 1
Me myself and I
  • 3,990
  • 1
  • 23
  • 47

1 Answers1

6

Because s++ increments the pointer by the sizeof(S), not sizeof(D), yet s actually points to the array of D at run-time.

  • The first iteration happens to be aligned with S::val of the first array element (which is 0),
  • the second with D::val of the first element (which is 1),
  • the third with the S::val of the second element (which is 0)
  • and so on...

This is essentially an undefined behavior. If your classes looked differently (or a platform with different alignment was used), you'd receive different and even more baffling results.

If you don't need polymorphism, just declare the function to receive an array of D (not S). If you do need the polymorphism, you should consider using an array of (smart) pointers, instead of the array of concrete elements (and access the data through virtual functions instead of direct field access).

Branko Dimitrijevic
  • 50,809
  • 10
  • 93
  • 167
  • Great answer! But why is this undefined behavior? – Me myself and I Jan 25 '13 at 18:49
  • @David Unfortunately, I'm not a standard-peeper, so I can't point you to the exact paragraph in the C++ standard that defines this (and I'm sure it's there!). Logically (and independently from C++), value arrays are not [covariant](http://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)), only reference arrays are. – Branko Dimitrijevic Jan 25 '13 at 18:56