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:
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)}}. |
The function walk should use a vector and an iterator. (This is left as an exercise for the reader.)
Using arrays polymorphically can result in memory corruption which could lead to an attacker being able to execute arbitrary code.