哪些函数不可以成为虚函数?构造函数和析构函数可以是虚函数吗?_构造函数 析构函数 静态成员函数 内联函数 不能是虚函数-程序员宅基地

技术标签: C++语言特性  

哪些函数不能成为虚函数?

  1. 普通函数:普通函数不属于成员函数,是不能被继承的。普通函数只能被重载,不能被重写,因此声明为虚函数没有意义。因为编译器会在编译时绑定函数。
  2. 构造函数:当调用了构造函数才能产生对象,通过对象才能调用虚函数,这显然矛盾。
  3. 静态成员函数:静态成员函数是属于类的,不依赖于对象调用,所以也不能成为虚函数。
  4. 友元函数:友元函数不属于类的成员函数,不能被继承。对于没有继承特性的函数没有虚函数的说法。
  5. 内联函数:内联函数在编译时就被展开,它不能产生函数符号,所以不能往虚表中存放,自然就不能成为虚函数。

构造函数不能为虚函数的再解释

1.虚函数调用是在部分信息下完成工作的机制,允许我们只知道接口而不知道对象的确切类型。 要创建一个对象,你需要知道对象的完整信息。 特别是,你需要知道你想要创建的确切类型。 因此,构造函数不应该被定义为虚函数。

2.虚函数对应一张虚函数表,这个虚函数表是存储在对象的内存空间的,如果构造函数是虚函数就需要通过虚函数表来调用,可是对象还没有实例化,也就是内存空间还没有,找不到虚函数表,所以构造函数是不能声明为虚函数的。

析构函数作为虚函数---虚析构

当子类有在堆上申请空间的操作,那么父类指针在释放时无法调用到子类的析构函数,这时就会造成内存泄漏。

解决方式:将父类中的析构函数改为虚析构或者纯虚析构。

虚析构和纯虚析构都可以解决父类指针释放子类对象,都需要有具体的函数实现。

语法:

  • 虚析构:virtual ~类名(){}
  • 纯虚析构:virtual ~类名() = 0;
                      类名::~类名(){}

下面一个例子:

#include<iostream>
using namespace std;
 
class Animal {
public:
	Animal(){
		cout << "Animal 构造函数调用!" << endl;
	}
	virtual void Speak() = 0;
 
	/*//析构函数加上virtual关键字,变成虚析构函数
	virtual ~Animal(){
		cout << "Animal虚析构函数调用!" << endl;
	}*/
 
	virtual ~Animal() = 0; //纯虚析构函数 
};
 
Animal::~Animal(){
	cout << "Animal 纯虚析构函数调用!" << endl;
}
 
//和包含普通纯虚函数的类一样,包含了纯虚析构函数的类也是一个抽象类。不能够被实例化。
 
class Cat : public Animal {
public:
	Cat(string name){
		cout << "Cat构造函数调用!" << endl;
		m_Name = new string(name);
	}
	virtual void Speak(){
		cout << *m_Name <<  "小猫在说话!" << endl;
	}
	~Cat(){
		cout << "Cat析构函数调用!" << endl;
		if (this->m_Name != NULL) {
			delete m_Name;
			m_Name = NULL;
		}
	}
public:
	string *m_Name;
};
 
int main() {
	Animal *animal = new Cat("Tom");
	animal->Speak();
	delete animal;
	return 0;
}

总结:

  • ​ 虚析构或纯虚析构就是用来解决通过父类指针释放子类对象
  • ​ 如果子类中没有堆区数据,可以不写为虚析构或纯虚析构
  • ​ 拥有纯虚析构函数的类也属于抽象类

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_21989927/article/details/110939246

智能推荐

深度学习的发展历程(思维导图、时间轴)_深度学习发展图-程序员宅基地

文章浏览阅读5.5k次,点赞6次,收藏13次。机器学习和深度学习的关系事实上,很多PGM也可从神经网络的方面来解释。尤其是VAE,它可看做二类的混合模型。当PGM的层太多时,学习和推断都很难。因此,Deep learning往往偏向于指代Deep neural network。从感知机到深度学习目前所说的深度学习实际上多指2006年开始的一系列模型。深度学习大火的原因:逐渐增加的数据量并行计算、分布式系统的发展硬件GPU等的发展最重要的是,其效果好,优于之前大火的SVM虽然目前深度学习的理论稍滞后,但其效果好呀~未来说比对_深度学习发展图

php游戏服务器教程,C++游戏服务器编程从入门到掌握视频教程(全)-程序员宅基地

文章浏览阅读255次。任务1: 课程预览PPT2-课程概述.mp43-IP详解第一部分.mp4任务4: 预览IP详解PPT5-IP详解第二部分.mp46-TCP详解第一部分(介绍 + 工作原理 + 头部详解).mp47-TCP详解第二部分(状态与连接详解).mp48-TCP详解第三部分(断开以及传送数据详解).mp49-TCP详解04(用wireshark工具查看TCP连接和断开和TCP杂项).mp4任务10: 预览T..._php 游戏视频教程

如何解决Invalid bound statement (not found):问题_invalid bound statement (not found): com.szkingdom-程序员宅基地

文章浏览阅读600次。在写ssm junit测试的时候一直报这个错, 配置文件以及包名都检查过了,一直没解决。各位大神帮帮忙org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.zking.ssm.mapper.LogininfoMapper.getUserByNameAndPwd at org.a..._invalid bound statement (not found): com.szkingdom.sfixp.parti.dao.partidao.

中心化傅里叶变换_傅里叶频谱中心化-程序员宅基地

文章浏览阅读6.8k次,点赞9次,收藏43次。参考文章:数字图像频谱中心化研究数字图像有时需要变换到频率做处理,比如滤波等。但直接对数字图像进行二维DFT变换得到的频谱图是高频在中间,低频在四角。为了把能量(在低频)集中起来便于使用滤波器,可以利用二维DFT的平移性质对频谱进行中心化。频谱图比较亮的地方就是低频,因为图像的能量一般都是集中在低频部分。所以推导出来的结论是:对数字图像的每个像素点的取值直接乘以(-1)^(x+y),x和y是像素坐标。这之后再做傅里叶变换,最后即为中心化后的傅里叶变换。代码:# 未中心化的傅里叶变_傅里叶频谱中心化

读《Boost程序库完全开发指南》_boost::适配器链-程序员宅基地

文章浏览阅读833次。读《Boost程序库完全开发指南》 2011-05-18 20:47:19| 分类: 读书|举报|字号 订阅 C++确实很复杂,神一样的0x不知道能否使C++变得纯粹和干爽? boost很复杂,感觉某些地方有过度设计和太过于就事论事的嫌疑,对实际开发工作的考虑太过于理想化。学习boost本身就是一个复杂度,有魄力在_boost::适配器链

css实例 css中id/class 详解样式表(外部样式表 内部样式表 内联样式 7种基础选择器 多重样式优先级 错误理解)[第一天]_css class-程序员宅基地

文章浏览阅读6.6k次,点赞4次,收藏18次。css实例css中的idcss中的class样式表外部样式表内部样式表内联样式7种基础选择器5种组合选择器后代选择和子代选择注意多重样式优先级选择器错误理解_css class

随便推点

十四、MySQL--主从复制和集群_mysql master和backup是主从还是集群-程序员宅基地

文章浏览阅读871次。0. 什么是主从复制?把主服务器(master)的bin日志复制到从服务器(slave)上再执行一遍,从而达到两台服务器上数据同步的效果。什么是集群?集群是一组相互独立的、通过高速网络互联的计算机,它们构成了一个组,并以单一系统的模式加以管理。一个客户与集群相互作用时,集群像是一个独立的服务器。集群配置是用于提高可用性和可缩放性。1.主从复制原理主数据库开启二进制日志,数据变更产生二进制日志从服务器的I/O线程读取主数据库的Bi..._mysql master和backup是主从还是集群

基于MATLAB的高斯白噪声和频率选择性衰落信道下的OFDM OTFS 16QAM QPSK LDPC Turbo调制解调误比特率性能仿真(附带代码和仿真说明)_ofdm系统在不同衰落信道下的误比特率性能分析-程序员宅基地

文章浏览阅读653次,点赞21次,收藏15次。同时,还对添加保护间隔、信道均衡等关键技术进行了详细讲解,并附带了仿真说明,使读者可以轻松理解和应用。通过本文的研究和分析,我们对OFDM和OTFS在高斯白噪声、频率选择性衰落信道下的误比特率性能有了更深入的理解。我们采用了16QAM和QPSK的调制方式、LDPC和Turbo的编码方式,并对添加保护间隔、信道均衡等关键技术进行了研究。Turbo编码也是一种常用的前向纠错码,它通过串并组合两个编码器的输出,并引入交织技术,在信道传输过程中提高了错误纠正能力。2.1 16QAM调制。OFDM调制解调技术。_ofdm系统在不同衰落信道下的误比特率性能分析

Android.mk 分析android buid工程需要的makefile知识点总结_android 解析android.mk工程-程序员宅基地

文章浏览阅读502次。1.0 make -C /home/wangxiancan/android -f build/core/main.mk all_modules -C 表示进入到某目录 执行(解析)其中的makefile -f 表示将后面的文件当做makefile文件解析 (make命令默认只识别如Makefile命名的文件,不过你会发现-C后面目录下已经有一个makefile了,并且这个m..._android 解析android.mk工程

UE5连接SQL数据库_ue5连接数据库-程序员宅基地

文章浏览阅读2.8k次。UE5连接SQL服务器_ue5连接数据库

spring boot 2.x整合dubbo-xml的方式_springboot 2.x 通过xml集成dubbo-程序员宅基地

文章浏览阅读514次。spring boot 2.x整合dubbo-xml的方式传统的项目都是基于xml配置文件的方式集成的dubbo,现在假如要升级框架到spring boot但是还是想用原来的方式整合dubbo,那么这篇文章对你应该有帮助项目结构生产者[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nFRGvMHz-1575526058549)(C:\Users\bhh\..._springboot 2.x 通过xml集成dubbo

Vue.js npm错误:transpileDependencies.map不是一个函数_transpiledependencies.map is not a function-程序员宅基地

文章浏览阅读483次。这个错误通常是由于npm版本不兼容导致的。在旧版本的npm中,transpileDependencies是一个字符串数组,我们可以直接配置需要编译的依赖库。而在较新版本的npm中,transpileDependencies被改成了一个对象,并且需要使用map()方法来处理。因此,如果我们在较新版本的npm中使用了旧版本的配置方式,就会导致transpileDependencies.map不是一个函数的错误。_transpiledependencies.map is not a function

推荐文章

热门文章

相关标签