1. 类的6个默认成员函数
如果一个类中什么成员都没有,简称为空类。空类中什么都没有吗?并不是,任何一个类在我们不写的情况下,都会自动生成下面6个默认的成员函数
2. 构造函数
2.1 前言
仔细观察如下代码:
#include<iostream>
using namespace std;
class Test
{
public:
void GetData()
{
m_data = 0;
}
private:
int m_data;
};
int main()
{
Test t;
t.GetData();
return 0;
}
我们可以看出,对于Test类,我们可以通过GetData公有方法给对象设置内容,但如果每次创建对象都调用该方法设置信息,未免有点麻烦,那能否在对象创建时就将信息设置进去呢?
面对这种情况构造函数就返回了其作用
2.2 什么是构造函数
构造函数:是一个特殊的成员函数,名字与类名相同,创建对象时由编译器自动调用,保证每个数据成员都有一个合适的初始值,并且在对象的生命周期内只调用一次(针对一个对象)
如下代码中Test()就是一个构造函数:
#include<iostream>
using namespace std;
class Test
{
public:
Test()
{
m_data = 0;
}
private:
int m_data;
};
int main()
{
Test t;
return 0;
}
2.3 构造函数的特性
构造函数虽然名称叫构造,但需要注意的是
构造函数的主要任务并不是开空间创造对象,而是初始化对象
- 函数名和类名相同
- 无返回值
对象实例化时编译器自动调用对应的构造函数
- 构造函数可以重载
测试如下:
#include<iostream>
using namespace std;
class Test
{
public:
//无参构造函数
Test()
{
}
//带参构造函数
Test(int data)
{
m_data = data;
}
private:
int m_data;
};
int main()
{
//调用无参构造函数
Test t1;
//调用带参构造函数
Test t2(20);
return 0;
}
注意:如果通过无参构造函数创建对象时,对象后面不用跟括号,否则就成了函数声明
- 如果类中没有定义构造函数,则编译器会自动生成一个无参的默认构造函数,若用户定义构造函数编译器将不再生成
- 无参构造函数和全缺省构造函数都称为默认构造函数,并且
默认构造函数只能有一个
3. 析构函数
3.1 前言
前面我们通过构造函数的学习,知道了一个对象的怎么来的,那么一个对象又是怎么没的呢?
于是我们引出了析构函数
3.2 析构函数
析构函数:与构造函数功能相反,析构函数不是完成对象的销毁,局部对象销毁工作是由编译器完成的。而
对象在销毁时会自动调用析构函数,完成类的一些资源清理工作。
如下代码中~Test()就是一个析构函数
#include<iostream>
using namespace std;
class Test
{
public:
Test(int data)
{
m_data = data;
cout << "Creat Test Obj" << endl;
}
~Test()
{
cout << "Free Test Obj" << endl;
}
private:
int m_data;
};
int main()
{
Test t(20);
return 0;
}
运行程序我们会看到,有构造就会有销毁,系统会自动调用析构函数
3.3 析构函数的特性
- 析构函数名是在类名前加上字符~
- 无参数无返回值
- 一个类有且只有一个析构函数。若未定义,则系统会自动生成默认的析构函数
- 对象生命周期结束时,编译器系统会自动调用析构函数
3.4 析构函数按什么顺序析构
析构函数按照构造的相反顺序进行析构
原因:以为对象都在栈区,先构造的对象往栈底放,所以析构按构造的相反顺序进行析构
测试如下:
#include<iostream>
using namespace std;
class Test
{
public:
Test(int data = 0)
{
m_data = data;
cout << "Creat Test Obj:" <<this<< endl;
}
~Test()
{
cout << "Free Test Obj:" <<this<< endl;
}
private:
int m_data;
};
int main()
{
Test t(12);
{
Test t1;
}
Test t2(3);
return 0;
}
如上图所示,先构造了一个t对象,再构造了一个t1对象,t1对象的生命周期结束了,析构了t1对象,因为按照构造的相反方向析构,所以先析构t2对象,最后析构t对象
4. 拷贝构造函数(对象初始化对象的过程)
4.1 前言
在现实生活中,可能存在一个与你一样的自己,我们称其为双胞胎,那么在创建对象时,是否可以创建一个与一个对象一模一样的新对象呢?
答案是可以的,我们可以使用拷贝构造函数来完成此操作
4.2 什么是拷贝构造函数
拷贝构造函数:只是单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用
如下图所示就是一个拷贝构造函数:
4.3 拷贝构造函数的特性
- 拷贝构造函数
是构造函数的一个重载
- 拷贝构造函数的参数只有一个且必须使用引用传参,使用传值的方式会引发无穷递归调用
- 若为定义,系统会生成默认的拷贝函数
4.4 拷贝构造函数参数中的const是否可以去掉
拷贝构造函数中的const不能去掉,const起到保护参数的作用
,虽然去掉const后程序依然可以正常运行不会报错,但会出现传入的参数被修改的情况(const是语义要求)
验证如下:
4.5 拷贝构造函数参数中&是否可以去掉
拷贝构造函数参数中的&不能去掉,首先去掉&编译不能通过,若去掉,则是传值的方式会引发无穷递归调用
;对象初始化对象会引发拷贝构造函数的调用,如下图所示:
5. 赋值重载函数
赋值重载函数:
- 需要检测是否自己给自己赋值
- 返回*this
如下图所示就是一个复制重载函数
6.普通对象的取址重载
用这种类型的指针接收这种类型对象的地址
如下图所示是一个普通对象的取址重载:
7.const对象的取址重载
注: 取地址及const取地址操作符这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,只有特殊情况才需要重载,比如想让别人获取到指定内容
转载:https://blog.csdn.net/weixin_50886514/article/details/115572801