Short answer: In C++, arrays of values are never polymorphic, even if their content is, and cannot be treated so. That is, you cannot treat an derived ad[N]
as if it was a base ab[N]
.
Long answer: The reason for this is deeply buried in C's pointer arithmetic. If you have an int* pi
and increment it ++pi
, it will not simply increment to the next memory address. If it did, it wouldn't point to the next int
since this doesn't start at the next address. So instead sizeof(int)
bytes are added to the pointer. (A concrete example might help: On architectures with 8bit char
types - char
being, by definition what C and C++ consider the architecture's byte size - and 32bit int
types, int
has the size of 4 bytes. Thus, ++pi
will add 4 to the pointers address, so that it points to the next int
.) The same arithmetic applies to all other pointer operations. So, for example, with int* pi2=pi+1
, pi2
will point sizeof(int)
bytes behind pi
, although pi2-pi
will yield 1.
So, presuming you understood the last paragraph, let's go back to arrays. If you have an array derived ad[N]
, the address of ad[1]
is sizeof(derived)
bytes greater than the address of ad[0]
. (That's disregarding alignment in order to not to further complicate the issue.) However, if you have a base* pb
pointing to ad[0]
, incrementing it will make it point sizeof(base)
behind the address of the first element - which, if (as is the case in your example) sizeof(base) < sizeof(derived)
, is not the address of ad[1]
, but somewhere in the middle of ad[0]
.
The only thing you can do to treat the array content as if it was all base classes, is to iterate over the array using a derived*
and cast this pointer to base*
within the loop:
derived d[5];
derived* begin = d;
const derived* end = d + sizeof(d)/sizeof(d[0]); // points one beyond the last element
while(begin != end)
{
base* pb = begin;
cout<< pb->_bval;
++begin;
}
(Note that I've also changed your code to use C++' idiomatic begin/end iterators.)