博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++以多态方式处理数组可能会遇到的问题
阅读量:6697 次
发布时间:2019-06-25

本文共 1871 字,大约阅读时间需要 6 分钟。

今天读《More Effective C++》时遇到一个条款:绝对不要以多态方式处理数组。以前自己也没有注意过,觉得有必要记录下来。

 

C++是允许通过base class的指针或引用来操作derived class所形成的数组的。但发生的事情可能会令你感到意外。下面举例说明:

基类和派生类是这样的:

class BST                            /*base class*/{public:    BST() : x1(1) {}    virtual ~BST()    {        cout << "Good Bye BST." << endl;    }    int x1;};class BalancedBST : public BST        /*derived class*/{public:    BalancedBST() : BST(), x2(2) {}     virtual ~BalancedBST()    {        cout << "Good Bye BalancedBST." << endl;    }    int x2;};

下面我重载了两个输出操作符:

/*输出base class*/ostream& operator<<(ostream& os, const BST& obj)        {    os << "class BST: " << obj.x1 << endl;    return os;}/*输出derived class*/ostream& operator<<(ostream& os, const BalancedBST& obj)    {    os << "Class BalancedBST: " << obj.x1 << ' ' << obj.x2 << endl;    return os;}

下面这个函数用于输出base class和derived class的数组。

/*输出base class和derived class数组*/void Print(ostream& os, const BST arr[], int n){    for (int i = 0; i < n; ++i)    {        os << arr[i];    }}

当以如下方式测试时,没有问题。

BST baseArr[10];Print(cout, baseArr, 10);    //好的,没问题,正常

当以如下方式测试时,就会出现问题。

BalancedBST deriveArr[10];Print(cout, deriveArr, 10);    //出错啦

编译器要想遍历数组中每一个元素,它必须知道每一个元素的大小。很明显,当print参数为BalancedBST数组时,编译器静态的将其数组大小当作BST的大小处理,以*(i+arr)的方式前进,结果是未知的。


还有一种情况,就是通过一个base class指针,删除一个由derived class组成的数组。

当以如下方式测试时,没有问题。

BST *base = new BST[10];delete [] base;                    //好的,没有问题BalancedBST *derived = new BalancedBST[10];delete [] derived;                //好的,没有问题

当我以如下方式测试时,就会有问题。

当数组被删除时,数组中每个元素的destructor会被调用,调用的顺序与构造顺序相反。也就是说执行delete [] base语句时,会产生类似下面的代码。

for (int i = 9; i >= 0; --i)    //编译器产生类似的代码,但是是错误的。{    base[i].BST::~BST();}

根本原因还是编译器把derived class数组成员的大小当作base class来计算数组元素的位置。

 

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

转载于:https://www.cnblogs.com/mengwang024/p/4548821.html

你可能感兴趣的文章
Variant 与 内存泄露
查看>>
WebSocket实战之————GatewayWorker使用笔记例子
查看>>
动手实践 Linux VLAN - 每天5分钟玩转 OpenStack(13)
查看>>
C语言 第八章 函数、指针与宏
查看>>
177.2. repository 管理
查看>>
[20150629]12c物化视图刷新Out of place
查看>>
基于.net开发chrome核心浏览器【四】
查看>>
Linux下编译安装Apache httpd 2.4
查看>>
.subversion
查看>>
TensorFlow训练单特征和多特征的线性回归
查看>>
linux的du使用方法
查看>>
STL容器删除元素的陷阱
查看>>
分析数据库CitusDB:提供弹性计算能力
查看>>
国产毫米波雷达领域的领头羊,木牛科技将在明年量产77GHz汽车雷达
查看>>
IOS7.1.1真的像网上流传的那么好?没有任何问题么??
查看>>
WiFi密码分享有妙招 不必口头相传
查看>>
剖析Docker Swarm和Mesos:是什么?如何结合?有什么优势?
查看>>
李飞飞:为什么计算机视觉对机器人如此重要?
查看>>
Unity AI副总裁Danny Lange:如何用AI助推游戏行业?
查看>>
《Effective Objective-C 2.0》1、熟悉Objective-C
查看>>