A polymorphic array element is accessed through a base-class array interface even when the stored elements have a derived type. Unlike a single base pointer, a derived array cannot safely substitute for a base array: pointer arithmetic advances by the wrong element size. section 8.10
Mistake: accepting a derived array as a base array
In the example, printArray(const B[]) accepts both B* and D*. The B array prints four zeros, while the D array prints 0, 1, 0, 1 because indexing uses B-sized steps. deleteArray also destroys the derived allocation through the base-array interface, producing only B destructor output. The apparent polymorphism therefore hides incorrect access and cleanup.
A safer incremental correction makes the functions templates. Type deduction preserves the actual element type, so indexing and delete[] use B for B arrays and D for D arrays without pretending that array polymorphism exists.
Listing 8.19 Passing an array with derived elements
const int SIZE = 4;
class B {
private:
int n;
public:
B(int n=0) : n(n) {}
~B() { std::cout << "destroying B\n"; } #1
int getN() const { return n; } #2
};
class D : public B {
int m;
public:
D() : B(0), m(1) {}
~D() { std::cout << "destroying D\n"; }
};
void printArray(const B a[]) {
for (int i = 0; i < SIZE; ++i)
std::cout << a[i].getN() << '\n'; #3
}
void deleteArray(const B a[]) { #4
delete [] a;
}
int main() {
B* bs = new B[SIZE];
printArray(bs);
deleteArray(bs);
D* ds = new D[SIZE];
printArray(ds);
deleteArray(ds);
return 0;
}
Inspect the complete failing program, including the base and derived classes, array-processing functions, and destructor behavior. section 8.10
