liveBook · Manning

Base class array

As explained in 100 C++ Mistakes and How to Avoid Them

A base class array is an array whose elements have a base class type and whose indexing uses that type's size.

A base class array stores elements as the base type. Although a derived-object pointer can replace a base-object pointer, a derived array cannot safely replace a base array: indexing advances by the base type's size. section 8.10

Mistake: passing a derived array as a base array

With B and D : public B, printArray(const B a[]) accepts both B* and D*. A B array prints four zeroes and destroys four B objects. A D array prints alternating values because a[i] advances as if each element were only a B; deleting it through B* destroys only the B subobjects, as the output demonstrates. section 8.10

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 example, including the base and derived classes, array-processing functions, and observed output. section 8.10

Avoid pretending that array parameters provide polymorphic element handling. Make the function type-preserving with a template, so B* uses B indexing and D* uses D indexing; the corrected version prints consistent values and destroys both D and B parts. section 8.10

How 100 C++ Mistakes and How to Avoid Them covers it

How deep it goes
Explains pointer arithmetic, demonstrates incorrect output and destruction, then applies templates as a correction.
Examples
Uses B and D arrays, printArray and deleteArray functions, contrasting output, and a templated replacement.
What it assumes
Assumes basic classes, inheritance, pointers, arrays, dynamic allocation, and function parameters.
What you can do after
Diagnose unsafe derived-array substitution and replace it with type-preserving templated array functions.
How it connects
Connects inheritance, polymorphism, the Liskov substitution principle, pointer arithmetic, and function templates.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of 100 C++ Mistakes and How to Avoid Them. The section links point to the parts of the book it draws on.