关于虚析构函数

cocogi 2004-04-02 09:14:37
在看Effective C++,学习虚析构函数时有点疑惑,程序如下
using namespace std;

class EnemyTarget
{
public:
EnemyTarget(void){cout << "Target Num:" << ++targetNum << endl;}
EnemyTarget(EnemyTarget&){++targetNum;}
virtual ~EnemyTarget(void){cout << "Target Num:" << --targetNum << endl;}
virtual void Display(){cout << "Target Display" << endl;}
static int TargetNum(){return targetNum;}
private:
static int targetNum;
};
int EnemyTarget::targetNum;

class EnemyTank: public EnemyTarget
{
public:
EnemyTank(void){cout << "Tank Num:" << ++tankNum << endl;}
EnemyTank(EnemyTank& rhs):EnemyTarget(rhs){++tankNum;}
~EnemyTank(void){cout << "Tank Num:" << --tankNum << endl;}
void Display(){cout << "Tank Display" << endl;}
static int TankNum(){return tankNum;}
private:
static int tankNum;
};
int EnemyTank::tankNum;
int main()
{
EnemyTarget *pTarget = new EnemyTank();
pTarget->Display();
delete pTarget;
return 0;
}

输出的结果为:
Target Num:1
Tank Num:1
Tank Display
Tank Num:0
Target Num:0
而不是:
Target Num:1
Tank Num:1
Tank Display
Tank Num:0

我的疑问是:
virtual ~EnemyTarget(void){cout << "Target Num:" << --targetNum << endl;}这句话是怎么会被调用的,这里不是virtual了吗?我用一个基类指针指向子类,那它应该调用子类的析构函数,为什么连基类析构函数也一块调用了呢?是不是虚析构函数不但会调用子类的析构,而且连基类的析构也一起调用了,而除了析构函数则指调用派生类的函数,就像display调用的就是子类。


...全文
19 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
cocogi 2004-04-03
  • 打赏
  • 举报
回复
多谢各位的解释!
:)
结贴
angelo23 2004-04-02
  • 打赏
  • 举报
回复
(上面的没说完就不小心发送了:( )
话也不是这么说的,毕竟调用虚函数会有时间和空间的额外负担,并不是说一定就应该把destructor定义为虚函数。
一般的原则是,当类的定义中有至少一个虚函数的时候,就应该定义virtual destructor。原因是,如果你定义了虚函数,那必然是要继承并且应用多态性了,那么这个时候为了保证调用适当的destructor,就应该将其定义为virtual destructor。
当然,即便没有其它的虚函数,如果子类的destructor是nontrivial的(比如牵涉到释放资源,或者输出某些信息,etc),那么也应该为基类定义virtual destructor
angelo23 2004-04-02
  • 打赏
  • 举报
回复
话也不是这么说的,毕竟调用virtual function会有时间和空间的额外负担,并不是说一定就应该把destructor定义为virtual function。
一般的原则是,当类的定义中有至少一个virtual function的时候,就应该定义virtual destructor。原因是,如果你定义了virtual function,那必然是要继承并且应用多态性了,那么这个时候为了保证调用适当的destructor
shallchen 2004-04-02
  • 打赏
  • 举报
回复
所以在设计类时,不管会不会被以后继承,把析构函数定义为虚析构函数是一个编程的好习惯。
angelo23 2004-04-02
  • 打赏
  • 举报
回复
P.S.你可以看成是子类的析构函数的用户定义代码后面加上了一句调用基类析构函数的语句,比如这样的伪代码:
~EnemyTank(void) {
cout << "Tank Num:" << --tankNum << endl;
this->EnemyTarget::~EnemyTarget(); //自动添加的
}
steel007 2004-04-02
  • 打赏
  • 举报
回复
在下的理解:

对于析构函数这么特殊的函数,在析构的过程中,会反向执行构造函数中的过程--先调用派生类的析构函数,再调用基类的析构函数。

使用virtual析构函数的用处在于用一个基类指针调用析构函数的时候会利用多态性正确的先调用派生类的析构函数。
angelo23 2004-04-02
  • 打赏
  • 举报
回复
因为子类对象的析构函数调用时,会自动调用基类的析构函数,调用的顺序和创建对象时构造函数的调用顺序相反

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧