条款3:不要对数组使用多态,例:不用基类指针删除派生类对象数组

错误代码:

//.h
class A{
	int a;
public:
	A(int v1=3):a(v1){...};
	virtual ~A();
};
class B:public A{
	double b;
public:
	B(int v1=1,int v2=2):b(v2),A(v1){...};
	virtual ~B();
};

//.cpp
void show(const A tmp[]int count){
	for(int i = 0;i<count;i++){ cout<<tmp[i].a;}
}
A* pt1 = new B[2];
delete [] pt1; //运行时错误,析构第二个失败,指针偏移后未找到析构函数
show(pt1,2); //运行时错误,输出第二个参数乱码

错误原因:
1、pt1 代表数组的起始地址,数组中其他元素(对象)内存地址与其实地址间隔为i*sizeof(一个在数组里的对象)
2、编译器在遇到需要遍历(如show函数、delete []等)数组的执行代码,需要知道数组的大小;
3、计算数组大小在编译期完成(sizeof静态绑定):编译器通过sizeof()运算符计算对象大小,但在编译阶段无法知道数组中存放的是基类还是派生类对象,因此只能计算指针对应对象类型大小
4、而派生类对象一般与基类对象大小不一,因此在指针+1过程中,出现偏移不足,导致输出错误或析构失败。

根本原因为:基类派生类对象大小不一导致指针按基类大小偏移出现的偏移错误。

小知识点:多态类对象在内存存放的第一个数据为虚指针。

改正代码:

A* pt1[] = {new B{1,2},new B{1,2}}; //定义指针数组,数组对象为指针
void show(const A* tmp[]int count){
	for(int i = 0;i<count;i++){ cout<<tmp[i]->a;}
}

正确原因:数组中存放指针,指针大小固定,因此在指针偏移时不会出现偏移不足问题。

总结:

1、不要对数组使用多态,因为数组对象大小确定在编译期,而多态对象大小是运行期确定。

发布了62 篇原创文章 · 获赞 0 · 访问量 954
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 游动-白 设计师: 上身试试

分享到微信朋友圈

×

扫一扫,手机浏览