继承的最重要特性之一就是,你可以通过指向基类的指针或者引用来操作派生类对象。但是,如果你通过基类指针或者引用来操作派生类所形成的数组,它绝对不会按你预期地运行。
例子:
原因就是array[i]其实是一个指针算术表达式的简写,所代表的是*(array + i)。(array + i)与array之间的距离有多远?答案是i*sizeof(数组中的对象),因为基类的大小sizeof比派生类小,所以第二个运行出错了。
同样地,尝试通过一个基类指针删除由派生类对象组成的数组,那么上述问题会以另一种形式出现。Delete []array;操作会调用父类的析构函数,而不会调用派生类的析构函数。C++语言规范中说,通过基类指针删除一个由派生类对象组成的数组,结果是未定义的。
解决该问题的办法是,不要让一个具体类继承自另一个具体类,这样可以带来很多好处,可以参见条款33。
例子:
//BalancedBST继承于BST类
void printBSTArray(ostream& s, const BST array[], int numElements)
{
for(int i = 0; i < numElements; i++){
s << array[i];
}
}
BST bstArray[10];
BST bbstArray[10];
printBSTArray(cout, bstArray, 10); //可以正常运行
printBSTArray(cout, bbstArray, 10); //运行异常
为什么第二个会运行异常?
原因就是array[i]其实是一个指针算术表达式的简写,所代表的是*(array + i)。(array + i)与array之间的距离有多远?答案是i*sizeof(数组中的对象),因为基类的大小sizeof比派生类小,所以第二个运行出错了。
同样地,尝试通过一个基类指针删除由派生类对象组成的数组,那么上述问题会以另一种形式出现。Delete []array;操作会调用父类的析构函数,而不会调用派生类的析构函数。C++语言规范中说,通过基类指针删除一个由派生类对象组成的数组,结果是未定义的。
解决该问题的办法是,不要让一个具体类继承自另一个具体类,这样可以带来很多好处,可以参见条款33。