1.在数组与多态混用的情况下,数组元素的访问会出现不可预期的结果(因为数组元素的访问会使用到下标运算)

将一个子类对象数组传递给一个父类对象数组声明的函数,编译器会允许这个行为,但是由于子类对象和父类对象的内存结构不同,会导致运行结果异常,因为在这种情况下,编译器仍然假设每一个元素的大小是父类对象元素的大小,但此时实际上每一个元素的大小是子类对象元素的大小

#include<bits/stdc++.h>
using namespace std; class BST
{
public:
char c;
}; class balancedBST:public BST//公有继承
{
public:
int x;
}; void printBSTArray(ostream& s,const BST array[],int numElements)//打印基类数组,注意数组的类型为基类!
{
for(int i=0;i<numElements;i++)
s<<array[i].c;
s<<endl;
} int main()
{
BST array[3];
for(int i=0;i<3;i++)
array[i].c='A'+i; printBSTArray(cout,array,3);//传递进入函数的是基类数组,打印正常 balancedBST barray[3];
for(int i=0;i<3;i++)
{
barray[i].x=i+1;
barray[i].c='a'+i;
} printBSTArray(cout,barray,3);//传递进入函数的是子类数组,打印异常!
/*
异常的原因:
因为函数定义的时候该对象的数组定义的是为基类类型,所以编译器在后续的操作中,
无论传入函数的是基类对象数组还是子类对象数组,都将视为基类对象数组
而基类对象的内存结构和子类对象的内存结构是不一样的
这样,通过下标访问到的东西,其实不是你想访问的东西 array[i] *(array+i)
array[0]和array[i] 之间相隔 i*sizeof(BST) 函数是按照i*sizeof(BST)算的,而如果你传入的是基类对象数组,也按照这样算的话,肯定是访问不到你想要的东西的
*/ } /*
运行结果:
ABC
ai
*/

2.在多态与数组混用的情况下,数组元素的删除也存在问题,会使用到没有定义的操作(通过基类指针来删除子类对象数组的行为在C++中是未定义的!)

#include<bits/stdc++.h>
using namespace std; class BST
{
public:
char c;
}; class balancedBST:public BST//公有继承
{
public:
int x;
}; void deleteArray(ostream& logStream,BST array[])
{
logStream<<"Deleting array at adress: "<<static_cast<void*>(array)<<endl;
delete [] array;//该操作的底层其实使用了下标,如果传入的是子类对象数组,那么通过基类指针来删除子类对象数组的行为在C++中是未定义的!
} int main()
{
BST *array =new BST[3];
balancedBST *barray =new balancedBST[3]; deleteArray(cout,array);//传入的是基类对象 deleteArray(cout,barray);//传入的是子类对象,存在问题,底层使用了未定义的操作
}

总结:那么如何避免上述两种问题呢?

第一个办法是避免采用多态方式来处理数组

第二个方法是避免让一共具体类继承自另外一个具体类

【More Effective C++ 条款3】最好不要以多态方式处理数组的更多相关文章

  1. [More Effective C++]条款22有关返回值优化的验证结果

    (这里的验证结果是针对返回值优化的,其实和条款22本身所说的,考虑以操作符复合形式(op=)取代其独身形式(op),关系不大.书生注) 在[More Effective C++]条款22的最后,在返回 ...

  2. More Effective C++ 条款0,1

    More Effective C++ 条款0,1 条款0 关于编译器 不同的编译器支持C++的特性能力不同.有些编译器不支持bool类型,此时可用 enum bool{false, true};枚举类 ...

  3. Effective C++ 条款08:别让异常逃离析构函数

    1.别让异常逃离析构函数的原因 <Effective C++>第三版中条款08建议不要在析构函数中抛出异常,原因是C++异常机制不能同时处理两个或两个以上的异常.多个异常同时存在的情况下, ...

  4. Effective C++ -----条款28:避免返回handles指向对象内部成分

    避免返回handles(包括reference.指针.迭代器)指向对象内部.遵守这个条款可增加封装性,帮助const成员函数的行为像个const,并将发生“虚吊号码牌”(dangling handle ...

  5. Effective C++ -----条款21:必须返回对象时,别妄想返回其reference

    绝不要返回pointer或reference指向一个local stack对象,或返回reference指向一个heap-allocated对象,或返回pointer或reference指向一个loc ...

  6. Effective C++ -----条款19:设计class犹如设计type

    Class的设计就是type的设计.在定义一个新type之前,请确定你已经考虑过本条款覆盖的所有讨论主题. 新type的对象应该如何被创建和销毁? 对象的初始化和对象的赋值该有什么样的区别? 新typ ...

  7. Effective C++ -----条款18:让接口容易被正确使用,不易被误用

    好的接口很容易被正确使用,不容易被误用.你应该在你IDE所有接口中努力达成这些性质. “促进正确使用”的办法包括接口的一致性,以及与内置类型的行为兼容. “阻止误用"的办法包括建立新类型.限 ...

  8. Effective C++:条款27——条款

    条款27:尽量少做转型动作 单一对象可能拥有一个以上的地址!

  9. Effective C++ 条款45

    本节条款的题目是运用成员模板接受全部兼容类型 作者阐述自己的观点是通过智能指针的样例. 在学习本节条款之前我们要先明确关于隐式转化的问题 例如以下代码: #include<iostream> ...

随机推荐

  1. 关于前端ajax请求url为何添加一个随机数

    一.起因 我在做爬虫的时候发现很多网站上都在url上加一个随机数或者时间戳一开始我以为是啥加密后面发现其实他在后台解析的时候也不需要不排除有些网站他反爬就需要一个时间戳,那他加个随机数是做啥子 二.查 ...

  2. RabbitMQ、RPC、SaltStack "贡"具的使用

    消息队列 使用队列的场景 在程序系统中,例如外卖系统,订单系统,库存系统,优先级较高 发红包,发邮件,发短信,app消息推送等任务优先级很低,很适合交给消息队列去处理,以便于程序系统更快的处理其他请求 ...

  3. CSS animation属性

    定义和用法 animation属性是下列属性的一个缩写属性: animation-name animation-duration animation-timing-function animation ...

  4. SPC软控件提供商NWA的产品在各行业的应用(生命科学行业)

    在上一篇文章中,我们提到了NWA软件产品在各行业都有广泛的应用,并且就化工行业的应用展开了详细介绍.而在本文中,您将看到NWA产品在生命科学行业也扮演着不可替代的角色. Northwest Analy ...

  5. anaconda配置清华大学开源软件镜像

    配置镜像在anaconda安装好之后,默认的镜像是官方的,由于官网的镜像在境外,使用国内的镜像能够加快访问的速度.这里选择了清华的的镜像.镜像的地址如下:tuna.Anaconda 安装包可以到 ht ...

  6. LearnOpenGL.PBR.IBL

    概述: IBL:image based lighting,一种间接光照(indirect lighting)技术,将周围的环境存在一张环境贴图(基于现实世界或3D场景生成)里面,然后将环境贴图上的每一 ...

  7. Python 函数小程序初解

    目录 作业 ==程序代码自上往下运行,建议自上而下的完成下列任务== 作业 文件a.txt内容:每一行内容分别为商品名字,价钱,个数,求出本次购物花费的总钱数 sum = 0 f = open('a. ...

  8. 20180711模拟赛T3——聚变

    文件名: fusion 题目类型: 传统题 时间限制: 3秒 内存限制: 256MB 编译优化: 无 题目描述 知名科学家小A在2118年在计算机上实现了模拟聚变的过程. 我们将她研究的过程简化. 核 ...

  9. win10系统易升更新不成功c盘也满了,解决方法

    删除临时更新文件: 1)同时按下Windows键和R键,打开运行,输入services.msc 2)找到WindowsUpdate服务项,右键选择禁用. 3)打开c:\windows\Software ...

  10. JDOJ 1928: 排队买票

    JDOJ 1928: 排队买票 JDOJ传送门 Description 一场演唱会即将举行.现有n个歌迷排队买票,一个人买一张,而售票处规定,一个人每次最多只能买两张票.假设第i位歌迷买一张票需要时间 ...