守望者--AIR技术交流

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

搜索
热搜: ANE FlasCC 炼金术
查看: 756|回复: 0

[C++] C++以多态方式处理数组可能会遇到的问题

[复制链接]
  • TA的每日心情
    擦汗
    2018-4-10 15:18
  • 签到天数: 447 天

    [LV.9]以坛为家II

    1742

    主题

    2094

    帖子

    13万

    积分

    超级版主

    Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

    威望
    562
    贡献
    29
    金币
    51691
    钢镚
    1422

    开源英雄守望者

    发表于 2015-6-3 15:53:49 | 显示全部楼层 |阅读模式

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


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

    基类和派生类是这样的:

    1. class BST                            /*base class*/
    2. {
    3. public:
    4.     BST() : x1(1) {}
    5.     virtual ~BST()
    6.     {
    7.         cout << "Good Bye BST." << endl;
    8.     }
    9.     int x1;
    10. };

    11. class BalancedBST : public BST        /*derived class*/
    12. {
    13. public:
    14.     BalancedBST() : BST(), x2(2) {}
    15.     virtual ~BalancedBST()
    16.     {
    17.         cout << "Good Bye BalancedBST." << endl;
    18.     }
    19.     int x2;
    20. };
    复制代码
    下面我重载了两个输出操作符:

    1. /*输出base class*/
    2. ostream& operator<<(ostream& os, const BST& obj)        
    3. {
    4.     os << "class BST: " << obj.x1 << endl;
    5.     return os;
    6. }

    7. /*输出derived class*/
    8. ostream& operator<<(ostream& os, const BalancedBST& obj)   
    9. {
    10.     os << "Class BalancedBST: " << obj.x1 << ' ' << obj.x2 << endl;
    11.     return os;
    12. }
    复制代码
    下面这个函数用于输出base class和derived class的数组。

    1. /*输出base class和derived class数组*/
    2. void Print(ostream& os, const BST arr[], int n)
    3. {
    4.     for (int i = 0; i < n; ++i)
    5.     {
    6.         os << arr[i];
    7.     }
    8. }
    复制代码
    当以如下方式测试时,没有问题。

    1. BST baseArr[10];
    2. Print(cout, baseArr, 10);    //好的,没问题,正常
    复制代码
    当以如下方式测试时,就会出现问题。

    1. BalancedBST deriveArr[10];
    2. Print(cout, deriveArr, 10);    //出错啦
    复制代码


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


    还有一种情况,就是通过一个base class指针,删除一个由derived class组成的数组。当以如下方式测试时,没有问题。
    1. BST *base = new BST[10];
    2. delete [] base;                    //好的,没有问题

    3. BalancedBST *derived = new BalancedBST[10];
    4. delete [] derived;                //好的,没有问题
    复制代码
    当我以如下方式测试时,就会有问题。
    当数组被删除时,数组中每个元素的destructor会被调用,调用的顺序与构造顺序相反。也就是说执行delete [] base语句时,会产生类似下面的代码。
    1. for (int i = 9; i >= 0; --i)    //编译器产生类似的代码,但是是错误的。
    2. {
    3.     base[i].BST::~BST();
    4. }
    复制代码
    根本原因还是编译器把derived class数组成员的大小当作base class来计算数组元素的位置。 C++规定,通过base class指针删除一个由derived class objects构成的数组,其结果是未定义的。所以,多态和指针算术不能混用,数组对象几乎总会涉及指针的算术运算,因而数组和多态不要混用。

    本文来自:http://www.cnblogs.com/mengwang024/p/4548821.html


    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    守望者AIR技术交流社区(www.airmyth.com)
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    
    关闭

    站长推荐上一条 /4 下一条

    QQ|手机版|Archiver|网站地图|小黑屋|守望者 ( 京ICP备14061876号

    GMT+8, 2019-8-18 13:13 , Processed in 0.039709 second(s), 34 queries .

    守望者AIR

    守望者AIR技术交流社区

    本站成立于 2014年12月31日

    快速回复 返回顶部 返回列表