Consider the following program.
#include<iostream>
using namespace std;
class base
{
public:
int _bval;
base():_bval(0){}
};
class derived:public base
{
public:
int _dval;
derived():base(),_dval(1){}
};
int main()
{
derived d[5];
base *p;
p=d;
for(int i=0;i<5;++i,++p)
cout<<p->_bval;
}
The output of the above program is 01010.
I thought the output would be 00000 because the value of _bval was initialized to 0(each time) by the base class constructor.
But why is the output different from 00000?
What am I missing?
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 abase ab[N].Long answer: The reason for this is deeply buried in C’s pointer arithmetic. If you have an
int* piand increment it++pi, it will not simply increment to the next memory address. If it did, it wouldn’t point to the nextintsince this doesn’t start at the next address. So insteadsizeof(int)bytes are added to the pointer. (A concrete example might help: On architectures with 8bitchartypes –charbeing, by definition what C and C++ consider the architecture’s byte size – and 32bitinttypes,inthas the size of 4 bytes. Thus,++piwill add 4 to the pointers address, so that it points to the nextint.) The same arithmetic applies to all other pointer operations. So, for example, withint* pi2=pi+1,pi2will pointsizeof(int)bytes behindpi, althoughpi2-piwill 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 ofad[1]issizeof(derived)bytes greater than the address ofad[0]. (That’s disregarding alignment in order to not to further complicate the issue.) However, if you have abase* pbpointing toad[0], incrementing it will make it pointsizeof(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 ofad[1], but somewhere in the middle ofad[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 tobase*within the loop:(Note that I’ve also changed your code to use C++’ idiomatic begin/end iterators.)