More Effective C++

More Effective C++ ,第1张

多态指的是可以通过基类类型的指针或引用, 来 *** 作派生类的对象. 然而通过基类类型的指针或引用,来 *** 作派生类的对象数组, 则没有任何保证如预期般运作.

有一个class BST以及继承自BST的class BalancedBST:

class BST
{
public:
    BST():bst1(-1),bst2(-2){}
    virtual ~BST(){cout << "BST::~BST" << endl;}
    virtual ostream& operator<<(ostream& os) const
    {
        os << "BST::operator<<:" << bst1 << "," << bst2 << endl;
        return os;
    }
private:
    int bst1;
    int bst2;
};

class BalancedBST: public BST
{
public:
    BalancedBST():bbst1(1), bbst2(2){}
    virtual ~BalancedBST(){cout << "BalancedBST::~BalancedBST" << endl;}
    virtual ostream& operator<<(ostream& os) const
    {
        os << "BalancedBST::operator<<:" << bbst1 << "," << bbst2 << endl;
        return os;
    }
private:
    int bbst1;
    int bbst2;
};

为了让输出BST类族, 惯用 cout<

ostream& operator<<(ostream& os, const BST& bst)
{
    bst << os;
    return os;
}

然后通过遍历指向基类的指针或引用(数组名作为函数参数会被退化为基类对象数组首地址):

void printBSTArray1(ostream& s, const BST array[], int numEles)
{
    cout << "printBSTArray1:" << endl;
    for (int i = 0; i < numEles; ++i) {
        array[i]<

经运行“以基类类型的指针,来 *** 作派生类的对象数组“会发生crash, 而“以基类类型的指针,来 *** 作基类的对象数组“则没有问题:

BST BSTArray[10];
BalancedBST BalancedBSTArray[10];

printBSTArray1(cout, BSTArray, 10);           //ok
printBSTArray1(cout, BalancedBSTArray, 10);   //crash

这是因为array[i]代表 *(array+i), 在编译阶段编译器便静态决定了数组中的每个对象大小, 只会以固定 sizeof(BST)进行指针的移动. 而通常带有数据成员的派生类的大小和基类通常不同, 编译器所产生的指针算数表达式对派生类对象数组是错误的, 结果不可预期.

同样, C++规范说通过基类的指针删除派生类对象数组, 结果也是未定义的:

void deleteArray(ostream& logstream, BST array[])
{
    logstream << "deleting array at address " << static_cast(array) << endl;
    delete [] array;
}

BST* balTree = new BalancedBST;
delete balTree;

cout << "===============" << endl;

BalancedBST* balTreeArray = new BalancedBST[4];
deleteArray(cout, balTreeArray);

结果:

BalancedBST::~BalancedBST
BST::~BST
===============
deleting array at address 0x100705688
BST::~BST
BST::~BST
BST::~BST
BST::~BST

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/921159.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-16
下一篇2022-05-16

发表评论

登录后才能评论

评论列表(0条)