虚函数与构造函数、析构函数

转自 http://blog.csdn.net/livelylittlefish/article/details/2198514

构造函数:为对象分配存储空间,使一个对象初始化;

析构函数:在该对象生命期完结时做相应的扫尾工作并释放分配的内存;

 

构造函数不能是虚函数的原因:

1、概念上说,虚函数机制只有在应用于地址时才有效,因为地址在编译阶段提供的类型信息不完整。

构造函数的功能是为一个对象在内存中分配空间,也就是说,此时该对象的类型已经确定了,编译系统确切地知道应该调用哪个类的构造函数,不需要也不可能应用动态绑定。

2、从实现上来说,每个对象的VPTR(指向本类虚函数的指针)是需要构造函数来初始化的(由编译系统自动实现),在构造函数还没有调用之前,VPTR没有形成,根本就不可能实现动态绑定。

 

当构造函数内部有虚函数时,会出现什么情况呢?

结果是,只有在该类中的虚函数版本被调用,也就是说,构造函数中,虚函数机制不起作用了,调用虚函数如同调用一般的成员函数一样。

 

析构函数可以是虚函数,而且应该被声明为虚函数。

1、析构函数与一般成员函数相似,析构函数被调用时,对象的构造已经完成,VPTR和VTABLE也已经被正确初始化,因此虚析构函数在实现上是可能的。

2、从设计角度来看,析构函数任务是释放内存,因此它必须确切知道被释放的对象的类型,否则可能破坏有用的数据,产生不可预知的后果。例如,我们用基类指针指向了派生类对象,那么释放内存时,必须是释放派生类对象的存储空间。所以,析构函数常被声明为虚函数,由于效率上原因,并不把析构函数缺省为虚函数但作为一条实践经验,可以给有虚函数的每个基类声明虚析构函数。

 

当析构函数内部有虚函数时,又如何工作呢?与构造函数相同,只有“局部”的版本被调用,但是,行为相同,原因是不一样的。

构造函数只能调用“局部”版本,是因为调用是还没有派生类版本的信息。

析构函数则是因为派生版本的信息已经不可靠了。

析构函数的调用顺序与构造函数相反,是从派生类的析构函数到基类的析构函数。当某个类的析构函数被调用时,其下一级的析构函数已经被调用了,相应数据也已经丢失了,如果再调用虚函数的最后一级的版本,就相当于对一些不可靠的数据进行操作,这是非常危险的。

在析构函数中,虚函数机制也是不起作用的。

 

在构造函数和析构函数内部的虚函数机制是不起作用的,也就是说,调用的是“局部”版本,即该类中的虚函数版本被调用。

posted @   曦花  阅读(341)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示