More Effective C++(条款三:绝对不要以多态方式处理数组)

继承的重要性质之一:通过“指向基类的指针或引用”,操作继承类对象。

如此的指针或引用,其行为是多态的。

c++允许通过“基类的指针和引用”来操作“继承类对象形成的数组”。但是:

1、

class BST{...};
class BalanceBST:public BST{...};
void printBSTArray(ostream& s,const BST array[],int numElements)
{
    for(int i=0;i<numElements;++i)
    {
        s<<array[i];//假设BST对象有一个operator<<可用
    }
}

//将由BST对象组成的数组传给以上函数没问题
BST BSTArray[10];
...
printBSTArray(cout,BSTArray,10);//运行良好

//将一个由BalanceBST对象组成的数组传给以上函数:
BalanceBST bBSTArray[10];
...
printBSTArray(cout,bBSTArray,10);//运行结果不可预期

因为:

array[i]代表*(array+i)。array是个指向数组起始处的指针。array所指内存与array+i所指内存相距i*sizeof(数组中对象)。

为让编译器所产生代码能走访整个数组,编译器必须有能力决定数组中的对象大小。以上代码中array和array+i相距i*sizeof(BST)。

若给printBSTArray函数传一个由BalanceBST对象组成的数组,编译器会误导。此时它仍假设数组中每一元素大小为sizeof(BST),但其实每一元素大小为sizeof(BalanceBST)。这样编译器为printBSTArray函数产生的array[i]对于BalanceBST对象组成的数组而言是错的,不可预期。

继承类对象通常会比基类对象大(继承类通常比基类有更多数据成员)。

2、

通过基类指针删除一个由继承类对象组成的数组:

void deleteArray(ostream& logStream,BST array[])
{
    logStream<<static_cast<void*>(array);
    delete []array;
}
BalanceBST *balTreeArray=new BalanceBST[50];//产生一个BalanceBST数组
...
deleteArray(cout,balTreeArray);//记录此删除动作

当数组被删除,数组中每一个元素的destructor都必须被调用,当编译器看到:

delete []array;

会产生代码:

for(int i=数组中元素数目-1;i>=0;--i)
{
    array[i].BST::~BST();//调用array[i]的destructor
}

c++语言规范中说:

通过基类指针删除一个由继承类对象构成的数组,其结果未定义。(以上编译器产生的代码是行为错误的循环)

多态和数组不能混用。(数组对象几乎总是涉及指针的算术运算)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值