深入解析C++中的构造函数和析构函数
来源:互联网 发布:sql注入的危害 编辑:程序博客网 时间:2024/06/05 04:06
深入解析C++中的构造函数和析构函数
构造函数:
在类实例化对象时自动执行,对类中的数据进行初始化。构造函数可以重载,可以有多个,但是只能有一个缺省构造函数。
析构函数:
在撤销对象占用的内存之前,进行一些操作的函数。析构函数不能被重载,只能有一个。
调用构造函数和析构函数的顺序:
先构造的后析构,后构造的先折构。它相当于一个栈,先进后出。
#include<iostream>#include<string>using namespace std;class Student{ public: Student(string,string,string); ~Student(); void show(); private: string num; string name; string sex;};Student::Student(string nu,string na,string s){ num=nu; name=na; sex=s; cout<<name<<" is builded!"<<endl;}void Student::show(){ cout<<num<<"\t"<<name<<"\t"<<sex<<endl;}Student::~Student(){ cout<<name<<" is destoried!"<<endl;}int main(){ Student s1("001","千手","男"); s1.show(); Student s2("007","纲手","女"); s2.show(); cout<<"nihao"<<endl; cout<<endl; cout<<"NIHAO"<<endl; return 0;}
先构造的千手,结果后析构的千手;后构造的纲手,结果先折构的纲手。
特点:
在全局范围定义的对象和在函数中定义的静态(static)局部对象,只在main函数结束或者调用exit函数结束程序时,才调用析构函数。
如果是在函数中定义的对象,在建立对象时调用其构造函数,在函数调用结束、对象释放时先调用析构函数。
#include<iostream>#include<string>using namespace std;class Student{ public: Student(string,string); ~Student(); void show(); string num; string name;};Student::Student(string nu,string na){ num=nu; name=na; cout<<name<<" is builded!"<<endl<<endl;}void Student::show(){ cout<<num<<"\t"<<name<<endl<<endl;}Student::~Student(){ cout<<name<<" is destoried!"<<endl<<endl;}void fun(){ cout<<"============调用fun函数============"<<endl<<endl; Student s2("002","自动局部变量");//定义自动局部对象 s2.show(); static Student s3("003","静态局部变量");//定义静态局部变量 s3.show(); cout<<"===========fun函数调用结束=============="<<endl<<endl;}int main(){ Student s1("001","全局变量"); s1.show(); fun(); cout<<"\nthis is some content before the end\n";//这是一段位于main函数结束之前,函数调用之后的内容 cout<<endl; return 0;}
析构函数再探:为什么有的类的析构函数是虚函数?
以下内容转载自:http://blog.163.com/cindy_zhoulixia/blog/static/7361720920083229403237/
所有C++程序员对析构函数都不陌生,由于其简单且易理解,所以都能很快应用。这里我不说这些常用方法,若不知可参考C++书籍。而我这次所想说的是较微妙的技巧,常不被人注意,但却非常非常的重要。看以下代码:
#include <iostream.h>class CFunction{public:CFunction(){data = new char[64];};~CFunction(){delete [] data;};char *data;};class CFunctionEx : public CFunction{public:CFunctionEx(){m_data = new char[64];};~CFunctionEx(){delete [] m_data;};private:char *m_data;};void main(){CFunction *pCFun = new CFunctionEx;delete pCFun;}
你能看出什么问题吗?很显然,有内存泄漏。这是因为当删除pCFun时,它只调用了Cfunction的析构函数而没调用CfunctionEx的析构函数,所以导致内存泄漏。再看下例:
#include <iostream.h>class CBase{public:CBase(){data = new char[64];};~CBase(){delete [] data;};char *data;};class CFunction{public:CFunction(){};~CFunction(){};};class CFunctionEx : public CFunction{public:CFunctionEx(){};~CFunctionEx(){};private:CBase m_cbase;};void main(){CFunction *pCFun = new CFunctionEx;delete pCFun;}
你能看出什么问题吗?这里CfunctionEx和Cfunction中本身并没有分配内存,应该不会有内存泄漏。和上例一样当删除pCFun时,它只调用了Cfunction的析构函数而没调用CfunctionEx的析构函数,但CfunctionEx本身并没分配内存,是什么地方有内存泄漏我不说大家也应该知道了吧。不错是m_cbase,因为它是Cbase的实例且是CfunctionEx成员变量,当CfunctionEx的的析构函数没有被调用时,当然m_cbase的析构函数也没有被调用,所以Cbase中分配的内存被泄漏。
解决以上问题的方法很简单,就是使基类Cfunction的析构函数为虚函数就可以了。很简单,是吗?哈哈……
这样就得出一个结论,当你的基类的析构函数不为虚的话, 其子类中所有的成员变量的类中分配的内存也将可能泄漏。
这一点非常重要,因为很容易被遗漏。我就是为此这才写此文。
这里说的可能是因为,如果程序中没有以上示例类似写法(指用基类指针指向子类实例裕,虚函数是C++的精华,很少有人不用的,由其是在大中型软件项目中),就不会出现本文所说的内存泄漏。看来在基类中使析构函数为虚函数是如此的重要。所以强烈建议在基类中把析构函数声明为虚函数,但是只有你写的类并不做为基类时例外。
以上我在工作中碰到的问题,程序在VC++6中测试,内存泄漏对于一个高效的服务程序来说十分重要。我想可能大家也可能出现过这种问题,所以写出这篇文章,希望能给大家带来帮助。
再举一例
转载自:http://blog.csdn.net/starlee/article/details/619827
我们知道,用C++开发的时候,用来做基类的类的析构函数一般都是虚函数。可是,为什么要这样做呢?下面用一个小例子来说明:
有下面的两个类:
#include<iostream>using namespace std;class ClxBase{public: ClxBase() {}; virtual ~ClxBase() { cout << "Output from the destructor of class ClxBase!" << endl; }; virtual void DoSomething() { cout << "Do something in class ClxBase!" << endl; };};class ClxDerived : public ClxBase{public: ClxDerived() {}; ~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; }; void DoSomething() { cout << "Do something in class ClxDerived!" << endl; };};int main(){ ClxBase *pTest = new ClxDerived; pTest->DoSomething(); delete pTest; return 0;}
输出结果是:
Output from the destructor of class ClxDerived!
但是,如果把类ClxBase析构函数前的virtual去掉,那输出结果就是下面的样子了:
也就是说,类ClxDerived的析构函数根本没有被调用!一般情况下类的析构函数里面都是释放内存资源,而析构函数不被调用的话就会造成内存泄漏。我想所有的C++程序员都知道这样的危险性。当然,如果在析构函数中做了其他工作的话,那你的所有努力也都是白费力气。
所以,文章开头的那个问题的答案就是--这样做是为了当用一个基类的指针删除一个派生类的对象时,派生类的析构函数会被调用。
当然,并不是要把所有类的析构函数都写成虚函数。因为当类里面有虚函数的时候,编译器会给类添加一个虚函数表,里面来存放虚函数指针,这样就会增加类的存储空间。所以,只有当一个类被用来作为基类的时候,才把析构函数写成虚函数。
- 深入解析C++中的构造函数和析构函数
- 深入解析C++中的构造函数和析构函数
- 构造函数和析构函数解析
- 构造函数和析构函数解析
- 深入解析C++构造函数与析构函数
- 构造函数和析构函数【c++】
- [c++]构造函数和析构函数
- 【C#】构造函数和析构函数
- 【C++】构造函数和析构函数
- 【C++】构造函数和析构函数
- C++:构造函数和析构函数
- 【C++】构造函数&析构函数的解析(应用)
- 继承中构造函数和继承中的析构函数解析
- 构造函数和析构函数中的虚函数调用
- 构造函数和析构函数中的虚函数调用
- 构造函数和析构函数中的虚函数
- 构造函数和析构函数中的虚函数
- <C++>析构函数、虚析构函数和构造函数
- Linux那些事儿 之 戏说USB(4)最终奥义
- hdu 2719 The Seven Percent Solution(模拟)
- LAN、WAN、WLAN、VLAN 和 VPN 的区别
- 使用 8 位 YUV 格式的视频呈现
- oracle优化3
- 深入解析C++中的构造函数和析构函数
- 中断详解(一)——基本概念
- SLIC超像素(superpixel)算法
- C 语言_数组算法例子
- oracle优化4
- oracle优化6
- vc6.0中更改对话框背景色和字体颜色
- 使用Webmin管理VSFTP搭建的FTP服务器
- 【Leetcode】Numbers of 1 bits