【汇编 C++】类的构造与析构
目录
前言
一、类的构造函数
什么是构造函数?
构造函数的特点
构造函数的作用
二、类的析构函数
什么是析构函数?
析构函数的特点
小结
析构函数的作用
总结
结语
封面
前言
本文章将会可能会涉及到汇编的知识,不过没有关系,我会讲的尽量通俗易懂;
另外本篇文章开始前,建议了解下什么是函数重载,这个概念很简单的--有相同的函数名,但参数列表不相同的函数,就是函数重载;
一、类的构造函数
什么是构造函数?
和类具有相同名称,并且没有返回值类型的函数,就是类的构造函数
概念模糊、直接举例:
#include <stdio.h>
#include <windows.h>struct Test
{Test() // 和类具有相同的名、并且没有返回值{}
};int main()
{return 0;
}
构造函数的特点
直接先来说特点吧,然后论证:
1、构造函数在定义对象的时候被调用
2、构造函数可以进行函数重载,可以有很多个
3、创建对象时默认调用的是无参构造
证明1:
构造函数在定义对象的时候被调用;
论证如下:
#include <stdio.h>struct Test
{Test(){printf("你调用了构造函数\n"); // 此处下断点、如果该函数被调用肯定会停下来。}
};int main()
{Test te;printf("接力\n");return 0;
}
我们在Test()构造的输出语句上加断点、当程序调用Test的printf肯定会停下来,这个时候我们转到反汇编,单步步过、直到函数返回之后,就能知到刚刚是在哪里调用的构造函数了
vs2010:F7编译、F5调试、ALT+8反汇编:
F10一直运行到返回:
这里编译器做了优化,可以直接看出来是在Test定义对象的时候调用了构造。
证明2:
构造函数可以进行函数重载,可以有很多个;
论证如下:
#include <stdio.h>
#include <Windows.h>struct Test
{Test(){printf("你调用了构造函数\n"); // 此处下断点、如果该函数被调用肯定会停下来。}Test(int a){printf("重载%d\n",a);}Test(int a, int b){printf("重载%d\n",a+b);}
};int main()
{Test te;Test te1(1);Test te2(1,1); // 注意、调用有参的构造函数时,需要传递参数system("pause");return 0;
}
重载了两个,注意:调用有参数的构造时,需要传递参数。
运行可以通过:
证明3:
创建对象时默认调用的是无参构造;
论证如下:
#include <stdio.h>
#include <Windows.h>struct Test
{Test(int a){printf("重载%d\n",a);}Test(int a, int b){printf("重载%d\n",a+b);}
};int main()
{Test te; // 普通定义对象的方式、不带参数system("pause");return 0;
}
首先我们删除无参构造,看看能否编译通过:
不可以
然后删除有参构造:
#include <stdio.h>
#include <Windows.h>struct Test
{Test(){printf("你调用了构造函数\n"); // 此处下断点、如果该函数被调用肯定会停下来。}};int main()
{Test te;system("pause");return 0;
}
可以
全部都加上:
#include <stdio.h>
#include <Windows.h>struct Test
{Test(){printf("你调用了构造函数\n"); // 此处下断点、如果该函数被调用肯定会停下来。}Test(int a){printf("重载%d\n",a);}Test(int a, int b){printf("重载%d\n",a+b);}
};int main()
{Test te;system("pause");return 0;
}
运行结果:
这已经证明了,Test te;平常这样定义对象的时候,调用的是无参构造。如果需要调用有参构造,必须传入参数;
这个特点很简单、有参函数肯定要传参嘛,所以定义对象的时候肯定要传入参数啊;
但是这里建议无论什么时候写类,最好还是写上无参构造,哪怕什么都不做也尽量写上,避免不必要的麻烦。
构造函数的作用
一般用于初始化类的成员
如下:
#include <stdio.h>
#include <Windows.h>struct Test
{int x;int y;int z;Test(){}Test(int x,int y,int z) // 构造函数初始化对象{this->x = x;this->y = y;this->z = z; }};int main()
{Test te;Test te1(1,2,3); // 定义对象并调用有参构造进行初始化printf("%d %d %d\n",te1.x,te1.y,te1.z); // 输出看看是否初始化成功system("pause");return 0;
}
运行如下:
初始化成功。
二、类的析构函数
什么是析构函数?
类的构造函数名前加上'~'这个符号,就是类的析构函数
概念模糊、代码如下:
#include <stdio.h>
#include <Windows.h>struct Test
{Test(){printf("你调用了一次类的构造函数\n");}~Test(){printf("你调用了一次类的析构函数\n");}};int main()
{Test te;// system("pause"); // 这里就不要让程序停下来了,不然析构不了return 0;
}
~Test(){}就这个样子
析构函数的特点
依然直接先来说特点,然后论证:
1、析构函数不能重载、不能有参数
2、析构函数在变量声明周期结束时被调用
3、析构函数被调用分两种情况:堆栈中定义的对象、全局区中定义的对象
证明1:
析构函数不能重载、不能有参数;
编译不通过。
既然不能有参数,那重载更不可能了
证明成功。
证明2:
析构函数在变量声明周期结束时被调用;
局部变量的生命周期是在一个大括号内,即一个所处块结束。
所以:
#include <stdio.h>
#include <Windows.h>struct Test
{Test(){printf("你调用了一次类的构造函数\n");}~Test(){printf("你调用了一次类的析构函数\n");}
};int main()
{{Test te;printf("te生命周期即将结束。\n");} // 析构应该在这里被调用printf("te生命周期结束。\n");system("pause");return 0;
}
运行结果如下:
断点
结果
证明成功。
证明3:
析构函数被调用分两种情况:堆栈中定义的对象、全局区中定义的对象;
已知堆栈中定义的对象(局部变量)在块语句结束之后就会被调用,那么带有return的main函数是在返回前调用析构,还是返回后呢?
代码如下:
#include <stdio.h>
#include <Windows.h>struct Test
{Test(){printf("你调用了一次类的构造函数\n");}~Test(){printf("你调用了一次类的析构函数\n"); // 断点--汇编}
};int main()
{Test te;// system("pause"); // 不要使用pause,不然无法返回return 0;
}
断点-调试-汇编:
可以看到是在函数返回前被调用的。
如果在全局区定义的对象呢?
这个问题很难说,像我一样定义两个断点就行了,如下:
#include <stdio.h>
#include <Windows.h>struct Test
{Test(){printf("你调用了一次类的构造函数\n");}~Test() // 断点{printf("你调用了一次类的析构函数\n"); }
};Test te;int main()
{// system("pause"); // 不要使用pause,不然无法返回return 0; // 断点
}
运行:
发现一运行就断在了return,当我们发F10继续运行的时候,并没有直接调用析构,而是到了括号那里:
继续F10:
通过翻译,可以得知这就是进程结束时的一些收尾工作。
继续F10:
现在大概可以总结了,类的对象定义为全局变量时,是在main函数结束之后进程退出之前,调用的析构函数。
小结
当类的对象定义为局部变量时(堆栈),定义这个对象的块作用域结束时就会调用该对象的析构函数,如果在main函数这个块作用域中定义的对象,那么就是在return之前调用析构。
当类的对象定义为全局变量时(全局区),会在main函数return函数返回之后和进程结束之前,调用该对象的析构函数。
析构函数的作用
我们知道了析构函数都是在类的对象生命周期结束时被调用,那么就代表下面不会再使用到这个对象;所以析构函数一般用于一些收尾的工作,以防忘记。
比如当你使用了该对象的成员申请了内存(malloc、new等)、或者open了一些文件,那么可以在析构函数中free delete 或者close。
例如:
#include <stdio.h>
#include <Windows.h>struct Test
{int x;char* name;Test(){name = (char*)malloc(sizeof(char)*20); // 构造时动态申请}~Test(){if(this->name!=0) // 析构时判断是个否为空,不为空释放{free(name);name = 0;}}
};int main()
{Test te;return 0;
}
这里我就不运行了,大家可以自己测试下。
总结
构造函数
1、和类具有相同名称,并且没有返回值类型的函数,就是类的构造函数
2、构造函数在定义对象的时候被调用
3、构造函数可以进行函数重载,可以有很多个
4、创建对象时默认调用的是无参构造
析构函数
1、类的构造函数名前加上'~'这个符号,就是类的析构函数
2、析构函数不能重载、不能有参数
3、析构函数在变量声明周期结束时被调用
4、析构函数被调用分两种情况:堆栈中定义的对象、全局区中定义的对象
结语
作者水平不高、如有错还望指出;如有听不懂的地方,可以私信或评论,之后会更改
封面
【汇编 C++】类的构造与析构相关推荐
- Part7 继承与派生 7.4派生类的构造和析构
1派生类的构造函数 默认情况下:基类的构造函数不被继承,派生类需要定义自己的构造函数. C++11 规定:可用using语句继承基类构造函数.但是只能初始化从基类继承的成员.这时派生类新增成员可以通过 ...
- String类的构造与析构相关处理
String类原型: 1 Class String 2 { 3 Public: 4 String(const char *str); 5 String(const String &other) ...
- c++基础知识点(6)类的继承,构造,析构顺序,虚继承等
学习继承之前,我们先回顾下protected(保护)成员 protected 成员的特点与作用: -对建立其所在类对象的模块来说,它与private成员的性质相同 -对于其派生类来说,它与public ...
- php构造和析构方法,php5构造函数与析构函数实例
自php5起,有了构造函数与析构函数. 这使得php更富有面向对象的魅力了. 在php4时,构造函数用的是与类同名的函数来进行构造这个动作. 例如: 复制代码 代码示例: /* * myclass.p ...
- 转:Delphi2010新发现-类的构造和析构函数功能
Delphi2010发布了. 虽然凭着对Delphi的热爱第一时间就安装了,但是现在可能是年纪大了,对新事物缺乏兴趣了.一直都没有仔细研究. 今天有点时间试了一下新功能. 本来C#和Delphi.NE ...
- C++系列总结——构造与析构
前言 在使用资源前,我们需要做一些准备工作保证资源能正常使用,在使用完资源后,我们需要做一些扫尾工作保证资源没有泄露,这就是构造与析构了,这和编程语言是无关的,而是使用资源的一种方式.C++只不过是把 ...
- (转)剖析Delphi中的构造和析构
剖析Delphi中的构造和析构 1 Delphi中的对象模型: 2 1.1 对象名表示什么? 2 1.2 对象存储在哪里? 2 1.3 对象中存储了什么?它们是如何存储的? 3 2 构造函数与创建对象 ...
- C++对象模型8——构造函数和析构函数中对虚函数的调用、全局对象构造和析构、局部static数组的内存分配
一.构造函数和析构函数中对虚函数的调用 仍然以https://blog.csdn.net/Master_Cui/article/details/109957302中的代码为例 base3构造函数和析构 ...
- 【设计原则和建议】 构造和析构对象
良好的构造和析构对象,控制对象生命周期可以较大的提高程序的性能,降低GC的压力,减少BUG几率. 本文还是比较简单的,主要还是经验的总结,很多东西也许各位已经知道,也许不知道.希望大家一起讨论. 1. ...
最新文章
- 文档信息的向量化-词袋模型、gensim实现和词条分布
- 洛谷P2502:[HAOI2006]旅行
- C++学习笔记:(十)异常
- 软件测试反例,基于模型检测多反例对软件进行调试
- LVM--逻辑卷管理
- OC 中NSString与NSString 的比较
- transactionManager 以及datasource type解析
- 2 数据源配置_[Mybatis]-[基础支持层]-数据源信息-数据源详解
- php图片生成缩略图_php实现根据url自动生成缩略图的方法
- 代理模式(Proxy) 静态
- Log_Analysis_using_OSSEC.md
- 无刷直流电机常用计算公式
- 【编程须知】同样的代码linux与windows的运行结果不同
- 巨人肩膀上的迁移学习(2)---图像回归
- 狂神SpringBoot静态资源文件
- 学生对计算机课程的意见和建议怎么写,对学校的意见和建议5条怎么写
- vue2.x中slot-scope插槽在vue3.x中的新写法
- 宏病毒的研究与实例分析02——复合文档格式分析
- 6个开源项目提高GIS编程技能
- JAVA简单连接数据库(Mysql)
热门文章
- [Mac] 触控板鼠标点击(mouse-click)失灵
- elasticsearch-es查询并清理重复数据
- [淘宝客技术篇005]如何取站点id和推广位id
- ubuntu 18.04 nautilus无法显示图片、视频文件的缩略图(预览)
- MySQL8_基础_聚合函数
- php的循环有哪几种,PHP数组循环遍历的几种方式
- 模拟微信浏览器抓取数据
- Excel按单元格背景颜色查找单个单元格的2种操作
- java高级查询_SQL高级查询(转载)
- 【图形学】关于透视投影