构造函数传送门
一、析构函数
1、什么是析构函数
与构造函数一样也是一种特殊的成员函数,它会在对象释放的时候自动调用,负责一些收尾工作,如:保存数据、释放资源等。
2、函数格式
~类名(void)
{
}
3、析构函数的任务
负责释放在构造函数中获取到的所有资源。
执行过程:
1、先执行析构函数本身代码
2、调用成员变量的析构函数
3、调用父类的析构函数
- 注意:析构函数与构造函数的执行顺序刚好相反
#include <iostream>
using namespace std;
class Test
{
public:
Test(void)
{
cout<<"我是构造函数"<<endl;
}
~Test(void)
{
cout<<"我是析构函数"<<endl;
}
};
void func(void)
{
Test* t = new Test;
cout<<"-------"<<endl;
delete t;
}
int main(int argc,const char* argv[])
{
int n=3;
while(n--)
func();
}
二、缺省的析构函数,构造函数
1、 定义
在设计一个类时,如果没有显示实现构造函数与析构函数,编译器 会自动生成它们,也叫缺省的构造和析构函数。
但生成的并不是真正语法意义上的函数,而是功能意义上的函数。
编译器做为可执行指令的生成着,它有能力直接生成某些功能的二进制指令,不需要借助语言上的函数完成某些任务。
2、 什么时候需要显示实现构造函数
- 有成员需要初始化
- 需要一些参数做一些准备工作
- 需要在对象使用之前准备一些资源.如:申请一些堆内存
3.、什么时候需要显示实现析构函数
缺省的析构函数会自动释放编译器能看得到的所有资源。如:成员变量,类成员,父类
- 保存一些数据
- 成员变量中有指针,且指向堆内存。
三、类对象 创建过程与释放内存总结
创建:
分配内存 -> 父类构造 -> 成员构造 -> 自己的构造(初始化成员,申请准备内存等)
父类构造:按照继承表的顺序从左到右依次执行父类构造函数
成员构造:按照成员的声明顺序,从上到下依次执行成员变量的构造函数
释放:
自己的析构函数(保存数据,释放堆内存等) -> 成员析构 -> 父类的析构 -> 释放内存(对象)
成员析构:按照声明的顺序,从下到上依次执行成员变量的析构函数
父类析构:按照继承表从右到左依次执行父类的析构函数。
四、拷贝构造函数(赋值构造)
什么是拷贝构造函数
是一种特殊的构造函数,当使用一个对象初始化另一个新的对象时,就会调用隐藏的拷贝构造函数,它也是类自带构造函数之一,由编译器自动生成。
拷贝构造格式
类名(const 类名& 变量名)
{
}
调用拷贝构造
- 类名 对象 = 对象
- 使用对象作为函数的参数时(不使用引用)
拷贝构造的任务
负责把旧的类对象中的成员拷贝给新的对象(默认,浅拷贝)。
什么时候显式使用拷贝构造?
当类中有成员是指针,且该指针指向了一块堆内存,此时拷贝构造应该拷贝指针所指向的内存(深拷贝),而默认的浅拷贝只拷贝指针变量的值,这时候会导致指针指向的内存被delete从而内存崩溃,因此应该显示地拷贝构造。
#include <iostream>
using namespace std;
class Test
{
int num;
public:
Test(int num)
{
this->num = num;
}
Test(Test& t)
{
num = t.num;
cout << "我是拷贝构造" << endl;
}
void show(void)
{
cout << num << endl;
}
};
void func(Test t)
{
cout << __func__ << endl;
}
int main(int argc,const char* argv[])
{
Test t(100);
Test t1 = t; // 调用拷贝构造
t.show();
t1.show();
func(t);
}
七、赋值函数(赋值运算符)
什么是赋值函数
在C++中是把运算符当做函数处理的,当一个对象给另一个对象赋值时就会自动调用该函数
赋值函数格式
类& operator=(const 类& that)
{
}
#include <iostream>
using namespace std;
class Test
{
int num;
public:
Test(int num)
{
this->num = num;
}
void show(void)
{
cout << num << endl;
}
Test& operator=(const Test& that)
{
num = that.num;
cout << "我是赋值函数" << endl;
return *this;
}
};
int main(int argc,const char* argv[])
{
Test t(100);
Test t1(0);
(t1 = t).show(); //调用赋值函数
}
什么时候调用
对象 = 对象;
赋值函数的任务
与拷贝构造函数一样,负责把一个对象的内存拷贝给另一个对象(浅拷贝)。
什么时候显式实现赋值函数:
当需要显式实现拷贝构造时,就应该显示实现赋值函数。