【基础】关于数组与多态不能合用的一个实例

 

#include <iostream>
using namespace std;
//一组标记函数
void funT()
{
 cout<<"T"<<endl;
}
void funA()
{
 cout<<"A"<<endl;
}
void funB()
{
 cout<<"B"<<endl;
}
void funC()
{
 cout<<"C"<<endl;
}
 
typedef void ( *pVf )();
pVf exPf[4] = 
{  &funT, &funA,&funB,&funC }

class CT
{
public
:
 CT()
 {
  tDat = &exPf[0]
;     //指向虚表元素,模拟虚表指针VPTR
  cout<<"CT()"<<endl; 
 
}
 
 ~CT()
{ cout<<"~CT()"<<endl; }
private:
 pVf  * tDat;
};
class CA
{
public
:
 CA()
 {
  aDat = &exPf[1]
;  
  cout<<"CA()"<<endl;
 
}
 virtual ~CA();
private:
 pVf  * aDat;
};
CA::~CA()
{
 cout<<"~CA()"<<endl;
}
class CB:public CA
{
public
:
 CB()
 {
  bDat = &exPf[2]
;  
  cout<<"CB()"<<endl;
 
}
 
 ~CB()
{ cout<<"~CB()"<<endl; }
private:
 pVf  * bDat;
 CT bCt;
};
int main()
{
 CA * pa = new CB[2];
 delete []pa;
 return 0;
}

 


/*Linux/GCC输出结果为:
       CA()
       CT()
       CB()
       CA()
       CT()
       CB()
       B  //编译器析构pa[1],没有调用正确的析构函数
       ~CB() //编译器析构pa[0]
       ~CT()
       ~CA()


从结果中可以看出:
1:GCC编译器对虚表指针VPTR的摆放,是放在对象空间的起始处的.
2:析构对象的顺序与构造时相反.
3:类CA的内存布局:VPTR, aDat ;类CB的内存布局:VPTR, aDat,(即CA布局), bDat, tDat(CT布局)
4:执行delete []pa;操作时
 4.1:首先析构对象pa[1], 即计算pa[1]的地址,采用基址+偏移(编译期常量,此处是sizeof( CA ))
 4.2:根据多态性调用VPTR指向的虚表中的函数
 4.3:如果调用到CB::~CB(),则还会调用成员对象的析构函数和基类对象的析构函数.
 4.4:由于目标对象地址的计算方式编译期就确定,因此与实际情况不符,从而出错.
 
P.S.这个例子在VC编译器上能正确运行,是因为VC编译器为对象数组的构造和析构做了特殊处理~
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值