C++程序设计基础:析构函数详解
创作时间:
作者:
@小白创作中心
C++程序设计基础:析构函数详解
引用
CSDN
1.
https://blog.csdn.net/qq_40071585/article/details/145918481
青少年编程与数学 02-010 C++程序设计基础 26课题、析构函数
课题摘要: 本文详细解析了C++中析构函数的定义、特点、使用示例及虚析构函数的概念。析构函数是类的特殊成员函数,名称为类名前加
~,无返回类型和参数,用于对象生命周期结束时的资源清理。其特点包括唯一性、特定的自动调用时机(局部对象作用域结束、全局对象程序结束、动态对象delete时)以及可继承但不重写。示例中,Resource类展示了构造函数分配内存、析构函数释放内存的过程,以及局部和动态对象析构函数的调用。虚析构函数在基类中定义,确保通过基类指针或引用删除派生类对象时,派生类析构函数被调用,防止资源泄漏。
在C++中,析构函数是类的一个特殊成员函数,用于在对象生命周期结束时进行清理工作。以下是关于类的析构函数的详细解析:
一、析构函数的基本概念
- 定义方式
* 析构函数的名称是在类名前加上波浪号(`~`)。例如,对于一个名为`Car`的类,其析构函数就是`~Car()`。
* 它没有返回类型,也不能带任何参数。例如,`~Car()`是正确的,而`void ~Car()`或`~Car(int)`都是错误的。
- 作用
* 主要用于释放对象占用的资源,如动态分配的内存、打开的文件、网络连接等。当对象的生命周期结束时,析构函数会被自动调用。例如,如果一个类中有一个成员变量是指向动态分配内存的指针,析构函数可以释放这块内存,防止内存泄漏。
二、析构函数的特点
- 唯一性
* 一个类只能有一个析构函数。这与构造函数可以重载不同。因为析构函数没有参数,所以无法通过参数列表来区分不同的析构函数。
- 自动调用时机
* **局部对象** :当局部对象的作用域结束时,析构函数会被调用。例如,在一个函数中定义了一个局部对象,当函数执行完毕,对象的作用域结束,析构函数就会被调用。
* **全局对象** :当程序结束时,全局对象的析构函数会被调用。全局对象的生命周期从程序开始到程序结束,析构函数在程序即将结束时进行资源清理。
* **动态分配的对象** :当使用`delete`操作符删除动态分配的对象时,析构函数会被调用。例如,通过`new`关键字创建的对象,需要用`delete`来释放,此时析构函数会执行清理工作。
- 可以被继承但不被重写
* 析构函数可以被继承,派生类会继承基类的析构函数。但是,析构函数不能被重写。在多态的情况下,如果基类的析构函数是虚函数,那么通过基类指针或引用删除派生类对象时,会调用派生类的析构函数,从而保证资源能够被正确释放。
三、析构函数的使用示例
#include <iostream>
using namespace std;
class Resource {
private:
int* data;
public:
// 构造函数
Resource(int size) {
data = new int[size];
cout << "Resource allocated." << endl;
}
// 析构函数
~Resource() {
delete[] data;
cout << "Resource deallocated." << endl;
}
};
void testFunction() {
Resource localResource(10); // 局部对象,作用域结束时调用析构函数
}
int main() {
testFunction(); // localResource的作用域在这里结束
Resource* dynamicResource = new Resource(20); // 动态分配对象
delete dynamicResource; // 使用delete调用析构函数
return 0;
}
在这个示例中,Resource类有一个成员变量是指向动态分配内存的指针。在构造函数中分配内存,在析构函数中释放内存。testFunction函数中的localResource是一个局部对象,当testFunction函数执行完毕,localResource的作用域结束,其析构函数被调用。在main函数中,通过new创建了一个动态分配的对象dynamicResource,使用delete时会调用其析构函数来释放资源。
四、虚析构函数
- 定义
* 在基类中将析构函数声明为虚函数,即在析构函数前加上`virtual`关键字。例如,`virtual ~BaseClass()`。
- 作用
* 确保通过基类指针或引用删除派生类对象时,能够调用派生类的析构函数,从而避免资源泄漏。如果基类的析构函数不是虚函数,那么在这种情况下只会调用基类的析构函数,派生类的析构函数不会被调用,可能导致派生类中资源没有被释放。
- 示例
#include <iostream>
using namespace std;
class Base {
public:
Base() { cout << "Base constructor called." << endl; }
virtual ~Base() { cout << "Base destructor called." << endl; }
};
class Derived : public Base {
public:
Derived() { cout << "Derived constructor called." << endl; }
~Derived() { cout << "Derived destructor called." << endl; }
};
int main() {
Base* ptr = new Derived();
delete ptr; // 会先调用Derived的析构函数,再调用Base的析构函数
return 0;
}
在这个示例中,基类Base的析构函数是虚函数。当通过基类指针ptr删除派生类Derived的对象时,会先调用Derived的析构函数,再调用Base的析构函数,确保资源能够被正确释放。
热门推荐
心流体验:心理学与脑科学的视角
如何实现个人到团队
进销存系统产品录入完全指南
改变“牙套脸”的干货!正畸人士快收藏!
MySQL中varchar字段的最大长度真的是65535吗?
锂电池充放电方式曲线
MATLAB图卷积神经网络GCN处理分子数据集节点分类研究
守护星梦:为何要关注孩子睡眠?
古茶诗解析:苏轼系列之十九《鲁直以诗馈双井茶,次韵为谢》
探秘博士生活:国内研究生的真实现状与未来展望
数据质量管理:定义、评估维度、问题原因及解决方案
如何学习单片机:从入门到精通的全面指南
心理咨询师证书的实际应用价值有多大?
添枝加叶:文章中的细节描写指南
如何认识住房公积金的概念与作用?这种概念和作用如何深入理解?
为什么日本没能经历德国式的去军事化与去军国主义化?
浪漫剧中最常见的13种剧情和叙事元素
《斗笑社3》:以“熟人局”为纽带,传递真挚情感与欢乐
适合初学者的六西格玛管理培训教材有哪些?
如何用代码写出机器人三大法则
春节怎么译,要在文化认同与全球传播间找平衡
显微镜物镜的数值孔径与分辨率详解
如何明确上证指数的计算方式?这种计算方式有哪些实际应用?
餐具304铁锅普通?科学揭秘重金属安全真相
多彩沙发背景墙扮靓客厅
苯中毒的预防措施
阿米巴项目管理模式有哪些
德国刑事诉讼法中的间接证据:理论与实践
芝士与鸡蛋的营养搭配研究
睡眠不足+晚睡=血糖失控?