Because pointer arithmetic does not take account of polymorphism, a major problem with arrays is that they do not interact well with polymorphism Stroustrup 06, Meyers 06 as the following example illustrates:
Non-compliant Example
class Base { public: virtual void func(void) { cout << "Base" << endl; } }; class Derived : public Base { public: int i; Derived() { i = 0; } void func(void) { cout << "Derived " << ++i << endl; } }; void walk(class Base *bar, int count) { for (int i = 0; i < count; i++) { bar[i].func(); } } int main(void) { Base dis[5]; Derived dat[5]; walk(dis, 5); walk(dat, 5); // crashes }
In the last call to walk()
, dat[]
is treated as a Base[]
and the subscripting no longer works correctly when sizeof(Derived) != sizeof(Base)
. This is because walk()
incorrectly believes that the size of each element in bar[]
is sizeof(Base)
. To locate the second element in the array (located at bar[1]
), walk()
adds the sizeof(Base)
to the address bar
. Assuming the derived object is larger (which is often the case), the resulting pointer refers to a point within the first element and not to the start of the second element located at bar + sizeof(Derived)
.
Compliant Solution
The function walk
should use a vector and an iterator. (This is left as an exercise for the reader.)
References
- Meyers 06 Item 3: Never treat arrays polymorphically.
- Stroustrup 06 What's wrong with arrays?