简介

析构函数(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++中的析构函数相关推荐

  1. 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; ...

  2. java中priorityqueue_详解JAVA中priorityqueue的具体使用

    Java中PriorityQueue通过二叉小顶堆实现,可以用一棵完全二叉树表示.本文从Queue接口函数出发,结合生动的图解,深入浅出地分析PriorityQueue每个操作的具体过程和时间复杂度, ...

  3. java中implement_详解JAVA中implement和extends的区别

    详解JAVA中implement和extends的区别 extends是继承父类,只要那个类不是声明为final或者那个类定义为abstract的就能继承,Java中不支持多重继承,但是可以用接口来实 ...

  4. java中getclass_详解java中this.getClass()和super.getClass()的实例

    详解java中this.getClass()和super.getClass()的实例 前言: 遇到this.getClass()和super.getClass()的返回值感到疑惑,经过探索豁然开朗. ...

  5. c++语言static作用,详解c++中的 static 关键字及作用

    注:若没有特指是 静态成员时,默认都是普通成员: 1 类中的普通成员 类中的成员变量 和 成员函数 是分开存储的.其中, 1)每个对象都有独立的成员变量:成员变量可以存储在 栈空间.堆空间.全局数据区 ...

  6. java中匿名内部类详解_java 中匿名内部类的实例详解

    搜索热词 java 中匿名内部类的实例详解 原来的面貌: class TT extends Test{ void show() { System.out.println(s+"~~~哈哈&q ...

  7. python中configparser详解_Python中的ConfigParser模块使用详解

    1.基本的读取配置文件 -read(filename) 直接读取ini文件内容 -sections() 得到所有的section,并以列表的形式返回 -options(section) 得到该sect ...

  8. java中final详解_Java中final用法与详解

    Java中final用法与详解 final作为Java中经常用到的关键字,了解final的使用方法是非常有必要的.这里从final关键字在数据域.方法和类中三个方面分析final关键字的主要用法. f ...

  9. python 中cookie_详解Python中的Cookie模块使用

    最近在用GAE开发自己的博客程序.虽然GAE的API没有显式的提供操作Cookie的方法,但他现有的架构,使我们有足够的自由来操作Cookie. Cookie 模块,顾名思义,就是用来操作Cookie ...

  10. shell中正则表达式详解_Linux中的正则表达式

    点击上方Linux迷,关注我们 正文 来自:https://www.linuxmi.com/linux-zhengzebiaodashi.html 正则表达式就是用于匹配每行输入的一种模式,模式是指一 ...

最新文章

  1. codeforces round 416 div2补题
  2. FFT对信噪比的增益计算
  3. mybatis maven 代码生成器(mysql)
  4. 你的元器件为什么会无缘无故地失效了?
  5. PHP - 使用 Pear 进行安装和卸载包
  6. 什么是ACID理论(二阶段、三阶段提交、TCC)
  7. k3 审核流程图_3-金蝶K3操作流程图详解
  8. keepalived高可用集群学习以及实验总结
  9. txt形式进行传输WebShell图文演示!
  10. mysql unsigned 溢出_mysql unsigned 用法及相减出现补数溢出解决方法 | 学步园
  11. RDBMS DML DDL
  12. 4g模块注册上网 移远_物联网模组龙头移远通信
  13. 金山词霸 只能最大最小
  14. linux的视频格式转换软件,工具盘点:必备的Linux视频转换工具(1)
  15. 施乐3030服务器系统安装,施乐DW3030驱动安装步骤
  16. iOS 开发常见崩溃分析
  17. 为什么爱奇艺会显示联通免流量服务器,联通爱奇艺流量定向包是怎么回事啊,是不是开通之后,这一个月里面看视讯免流量的...
  18. 小学计算机课后总结怎么写,【小学信息技术工作总结11篇】_小学信息技术工作总结范文大全_2021年小学信息技术工作总结_东城教研...
  19. EUV光刻机内部揭秘!
  20. 用计算机自我介绍,计算机简单的自我介绍

热门文章

  1. java中打印俄罗斯方块游戏_java实现俄罗斯方块小游戏
  2. JVM调优实践:记录初次JVM调优经历
  3. 自学神经网络系列 —— 8 前馈神经网络
  4. Burp抓取MuMu模拟器数据包
  5. 搭建无线监控云存储服务器,搭建无线监控云存储服务器
  6. 我的第一个Python爬虫——谈心得
  7. Joint Autoregressive and Hierarchical Priors for Learned Image Compression文献复现
  8. 快速使用git、svn
  9. Leetcode︱448. Find All Numbers Disappeared in an Array找到所有数组中消失的数字.java
  10. 自组网 AODV路由协议 篇1