03. 绝对不要以多态(polymorphically)方式处理数组

继承的最重要性质之一就是:可以通过"指向base class objects"的pointers和references,来操作derived class objects。如此的pointers和references,其行为是多态的。

有如下例子:

class BST{...};
class BalanceBST : public BST{...};

考虑有个函数,打印BSTs数组中的每一个BST的内容:

void PrintBSTArray(ostream& s, const BST array[], int numElements)
{
	for (int i = 0; i < numElements; ++i)
	{
		s << array[i];
	}
}

当你将一个BST对象的数组传给此函数,没问题:

BST bstArray[10];
...
PrintBSTArray(cout, bstArray, 10); // 良好运行

但是如果将一个BalanceBST组成的数组传给此函数:

BalanceBST bstArray[10];
...
PrintBSTArray(cout, bstArray, 10); // 未定义行为

行为未定义。这是因为PrintBSTArray函数时,使用下标i访问array涉及到对数组array的处理(array[i] = *(array + i))。array是个指针,指向数组起始处。array所指内存和array + i相距多远?是i * sizeof(数组中的对象)。它会将传入的数组都处理成BST类型,因为其函数声明中array就是BST类型,这里不会有虚函数类似的处理。

如果你尝试删除数组,依旧传入BalanceBST数组

void DeleteArray(ostream& logStream, BST array[])
{
	...
	delete [] array;
}
BalanceBST* pArray = new Balance[50];
...
delete [] pArray;

虽然看不到,但其中依旧有指针运算表达式的存在。实际有如下处理:

for (int i  the number of elements in the array - 1; i >= 0; --i)
{
	array[i].BST::~BST(); // 调用array[i]的destructor
}

错误原因同上。

总结
通过base class指针删除一个有derived classes objects构成的数组,其结果未定义。多态和指针算术不能混用,数组对象几乎总是会涉及到指针的算数运算,所以数组和指针不能混用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值