Array operations almost always involve pointer arithmetic, so arrays and polymorphism don’t mix.
C++ allows us to manipulate arrays of derived class objects through base class pointers and references, but it almost nerver works athe way we want it to.
For example, suppose following base class BST
(binary search tree objects) and its derived class BalancedBST
:
|
|
For a function working with an array of BST
s, it works fine when we pass it an array of BST
objects:
|
|
However, when passing an array of BalancedBST
objects:
|
|
The compilers will accept this function call without complaint, but then for array[i
]`, they will generate code involving pointer arithmetic:
array[i]
is just shorthand for expression*(array+i)
- the distance between the memory location pointed to by
array
and byarray+i
is calculated throughi*sizeof(object in the array)
- the parameter
array
is declared to be of typearray-of-BST
, so each element of the array is regard asBST
, and thus the distance isi*sizeof(BST)
- the size of an object of type
BalancedBST
usually is larger than their base class ones’ size, because derived class usually has extra data members - If it is, the ointer arithmetic generated for
printBSTArray
will be wrong for arrays ofBalancedBST
objects
Another problem will pop up if we try to delete an array of derived class objects through a base class pointer:
|
|
There’s pointer arithmetic going on here, too: when compilers see the statement delete [] array;
, they will generate code that looks like this:
|
|
Now we understand why the language specification says that the result of deleting an array of derived class objects through a base class pointers is undefined: here, again, polymorphism meets pointer arithmetic.
In the point of software designing, as MECpp-item 33 suggests, we’re unlikely to make the mistake of treating an array polymorphically if we avoid having a concrete class (like BalancedBST
) inherit from another concrete class (such as BST
).