c 语言中析构函数,详解C++中的析构函数
简介
析构函数(Destructors),是对象的成员函数,没有返回值也没有参数,且一个类只有一个析构函数,当对象被销毁的时候调用,被销毁通常有这么几个情况。
函数执行结束
程序执行结束
程序块包含的局部变量
delete操作
什么时候要自己写析构函数?
编译器会自动创建默认的析构函数,通常都没有问题,但是当我们在类中动态分配了内存空间时,我们需要手段的回收这块空间,防止内存溢出。就像这样
class String
{
private:
char *s;
int size;
public:
String(char *); // constructor
~String(); // destructor
};
String::String(char *c)
{
size = strlen(c);
s = new char[size+1];
strcpy(s,c);
}
String::~String()
{
delete []s;
}
私有的析构函数
可以将析构函数的访问权限设置为private,设置时没有问题的,但是一个问题就是,通常的手段就没法调用析构函数了。
如下所示,程序结束后要调用析构函数,但是析构函数时私有的没法调用,所以会编译出错。
#include
using namespace std;
class Test {
private:
~Test() {}
};
int main()
{
Test t;
}
以下这样不会有问题,因为没有对象被建立,也不用析构
int main()
{
Test* t;
}
以下这样也不会有问题,因为动态分配的内存需要程序员手段释放,所以程序结束时没有释放内存,也没有调用析构函数。这里插一句,动态分配的内存如果不手动释放,程序结束后也会不会释放,但是现代操作系统可以帮我们释放,因为这个动态分配的内存和这个进程有关,操作系统应该可以捕获到这个泄露的内存从而释放。(查资料看到的)
int main()
{
Test* t = new Test;
}
如果使用delete来删除对象,会编译出错
int main()
{
Test* t = new Test;
delete t;//编译出错,无法调用私有的析构函数
}
可以利用Friend函数,进行对象的销毁,因为Friend可以访问私有成员,所以可以访问析构函数。
#include
class Test {
private:
~Test() {}
friend void destructTest(Test*);
};
void destructTest(Test* ptr)
{
delete ptr;
}
int main()
{
Test* ptr = new Test;
destructTest(ptr);
return 0;
}
或者给类写一个销毁的方法,在需要销毁的时候调用。
class Test {
public:
destroy(){delete this};
private:
~Test() {}
};
那么什么时候需要使用私有的析构函数呢?当我们只希望动态分配对象空间(在堆上)时候,用私有析构,就防止了在栈上分配,因为在编译阶段就会出错。
虚析构函数
当类用到多态的特性时候,使用虚析构函数。看如下的例子。
#include
using namespace std;
class Base
{
public:
Base(){
cout << "Base Constructor Called\n";
}
~Base(){
cout << "Base Destructor called\n";
}
};
class Derived1: public Base
{
public:
Derived1(){
cout << "Derived constructor called\n";
}
~Derived1(){
cout << "Derived destructor called\n";
}
};
int main()
{
Base *b = new Derived1();
delete b;
}
例子里的析构函数都不是虚函数,当我们想用基类的指针来删除派生类对象的时候,就出现了问题,“undefined behavior”,c++标准里规定,只由编译器实现,通常这时不会报错,会调用基类的析构函数。但这应该不是我们想要的,这会导致内存泄漏。所以要把析构函数置为虚函数。(msvc似乎不用给析构函数加virtual,默认就是虚的,gcc没有默认还是要加的)
另外虚析构函数可以是纯虚析构函数,但是要提供函数体,不然没法析构,因为虚析构函数和一般的虚函数的overide还不一样,虚析构函数要挨个执行,不提供函数体,会编译出错。
析构函数的执行顺序
派生类,成员对象,基类这样
class B
{public: virtual ~B(){cout<
};
class D
{public:virtual ~D(){cout<
} ;
class E
{public:virtual ~E(){cout<
} ;
class A
{public:virtual ~A(){cout<
};
class C:public A,B
{
public:virtual ~C(){cout<
private:
E e;
D d;
};
int main()
{
C *c;
c=new C();
delete c;
}
结果为
派生类执行了
成员D执行了
成员E执行了
基类B执行了
基类A执行了
参考
以上就是详解C++中的析构函数的详细内容,更多关于C++ 析构函数的资料请关注脚本之家其它相关文章!
c 语言中析构函数,详解C++中的析构函数相关推荐
- java switch中if_详解java中if语句和switch的使用
if语句 说起if语句,那么不得不提起三元运算符 a>b?c=0:c=1; 如果a>b结果为true,那么c=0,为false,c=1 那么下面看下if语句 if(a>b)c=0; ...
- java中priorityqueue_详解JAVA中priorityqueue的具体使用
Java中PriorityQueue通过二叉小顶堆实现,可以用一棵完全二叉树表示.本文从Queue接口函数出发,结合生动的图解,深入浅出地分析PriorityQueue每个操作的具体过程和时间复杂度, ...
- java中implement_详解JAVA中implement和extends的区别
详解JAVA中implement和extends的区别 extends是继承父类,只要那个类不是声明为final或者那个类定义为abstract的就能继承,Java中不支持多重继承,但是可以用接口来实 ...
- java中getclass_详解java中this.getClass()和super.getClass()的实例
详解java中this.getClass()和super.getClass()的实例 前言: 遇到this.getClass()和super.getClass()的返回值感到疑惑,经过探索豁然开朗. ...
- c++语言static作用,详解c++中的 static 关键字及作用
注:若没有特指是 静态成员时,默认都是普通成员: 1 类中的普通成员 类中的成员变量 和 成员函数 是分开存储的.其中, 1)每个对象都有独立的成员变量:成员变量可以存储在 栈空间.堆空间.全局数据区 ...
- java中匿名内部类详解_java 中匿名内部类的实例详解
搜索热词 java 中匿名内部类的实例详解 原来的面貌: class TT extends Test{ void show() { System.out.println(s+"~~~哈哈&q ...
- python中configparser详解_Python中的ConfigParser模块使用详解
1.基本的读取配置文件 -read(filename) 直接读取ini文件内容 -sections() 得到所有的section,并以列表的形式返回 -options(section) 得到该sect ...
- java中final详解_Java中final用法与详解
Java中final用法与详解 final作为Java中经常用到的关键字,了解final的使用方法是非常有必要的.这里从final关键字在数据域.方法和类中三个方面分析final关键字的主要用法. f ...
- python 中cookie_详解Python中的Cookie模块使用
最近在用GAE开发自己的博客程序.虽然GAE的API没有显式的提供操作Cookie的方法,但他现有的架构,使我们有足够的自由来操作Cookie. Cookie 模块,顾名思义,就是用来操作Cookie ...
- shell中正则表达式详解_Linux中的正则表达式
点击上方Linux迷,关注我们 正文 来自:https://www.linuxmi.com/linux-zhengzebiaodashi.html 正则表达式就是用于匹配每行输入的一种模式,模式是指一 ...
最新文章
- codeforces round 416 div2补题
- FFT对信噪比的增益计算
- mybatis maven 代码生成器(mysql)
- 你的元器件为什么会无缘无故地失效了?
- PHP - 使用 Pear 进行安装和卸载包
- 什么是ACID理论(二阶段、三阶段提交、TCC)
- k3 审核流程图_3-金蝶K3操作流程图详解
- keepalived高可用集群学习以及实验总结
- txt形式进行传输WebShell图文演示!
- mysql unsigned 溢出_mysql unsigned 用法及相减出现补数溢出解决方法 | 学步园
- RDBMS DML DDL
- 4g模块注册上网 移远_物联网模组龙头移远通信
- 金山词霸 只能最大最小
- linux的视频格式转换软件,工具盘点:必备的Linux视频转换工具(1)
- 施乐3030服务器系统安装,施乐DW3030驱动安装步骤
- iOS 开发常见崩溃分析
- 为什么爱奇艺会显示联通免流量服务器,联通爱奇艺流量定向包是怎么回事啊,是不是开通之后,这一个月里面看视讯免流量的...
- 小学计算机课后总结怎么写,【小学信息技术工作总结11篇】_小学信息技术工作总结范文大全_2021年小学信息技术工作总结_东城教研...
- EUV光刻机内部揭秘!
- 用计算机自我介绍,计算机简单的自我介绍
热门文章
- java中打印俄罗斯方块游戏_java实现俄罗斯方块小游戏
- JVM调优实践:记录初次JVM调优经历
- 自学神经网络系列 —— 8 前馈神经网络
- Burp抓取MuMu模拟器数据包
- 搭建无线监控云存储服务器,搭建无线监控云存储服务器
- 我的第一个Python爬虫——谈心得
- Joint Autoregressive and Hierarchical Priors for Learned Image Compression文献复现
- 快速使用git、svn
- Leetcode︱448. Find All Numbers Disappeared in an Array找到所有数组中消失的数字.java
- 自组网 AODV路由协议 篇1