构造/析构函数
构造函数(初始化类的函数)
让我命名我就叫它【初始化类函数】。它有以下特点:
1. 没有返回值类型(感觉像是参数采用引用的void函数),函数名和类名相同
2. 不同的初始化类函数之间可以重名但不重参(也就是可以【重载】)
3. 我感觉大部分的这种初始化类函数是为了处理private数据。就是让一个对象的私有数据成员,拥有属于它自己的值。
4. 如果不自己写构造函数,也会自己生成这个对象的构造函数,也就是【默认构造函数】。默认构造函数没有参数。使用这个默认构造函数生成默认的对象的时候,定义这个对象格式就是
ClassName obj;//不能是ClassName obj()
5. 如果要定义一个数组,这个数组的元素是一个个对象,那么这时候,这个数组所要构造的对象,对象所起源的类,类必须提供默认构造函数的定义。
6. 使用【初始化列表】来初始化成员数据。初始化列表,说白了就是一个列表【初始化是个形容词而不是动词,也就是,不是让我初始化一个列表,而是构造一个有初始值的列表对儿】。什么是列表,列表就是【AAA:BBB】这种类似于解释AAA成BBB的一个对儿。这个对儿就叫列表。
class MyClass {
private:
int num;
double value;
public:
MyClass(int n, double v) : num(n), value(v) {
// 构造函数体
}
};
在上面,就通过【ClassName(参1, 参2) : 私有变量(参1), 私有变量(参2) {其他函数操作}】就让私有数据成员有了初始值。
6. 【委派构造函数】主要作用就是减少代码重复和冗余。
class MyClass {
public:
MyClass(int x, int y) : m_x(x), m_y(y) {
// 构造函数的其他初始化操作
}
MyClass(int x) : MyClass(x, 0) {
// 委派构造函数,调用上面的构造函数
}
private:
int m_x;
int m_y;
};
当传入的参数符合第二个重构的MyClass函数的时候(也就是只有一个参数的时候),就先执行被委派的函数完成这些重复的工作,然后再完成一些其他的工作。
7. 【拷贝构造函数】
如果一个函数的参数是一个对象/的返回值是对象的时候,编译器会在已有对象的基础上生成新的对象。
class Person{
int id;
...
public:
Person(const Person& src){id = src.id;....}
...
};
拷贝构造函数创建了一个 已经存在的对象的 【副本】(我好像悟了)。
完整的一个例子:
运行结果:
【运行过程还是不太懂,之后再回来看看】
【感觉冒号的意思就是先提前完成一点小任务,比如赋初值、一些基本操作,然后再干大括号里面的活儿。因此是类名+冒号+自己的函数体。】
析构函数
我给它起名我肯定起个【擦屁股函数】
相比于之前的int、double,其实当我们使用完之后,编译器会自己主动回收用了的空间。但class是我们自己定义的数据类型,那么给 用这些数据类型定义好的数据 擦屁股,就成了我们需要做的工作。
1. 一个类【只有一个】析构函数,名字是【~类名】。这只是单纯的一个名字,编译器一看有个~,就会在不使用这个对象后,就执行这个函数。
2. 没有返回值,没有函数参数!
class ClassRoom{
int num;
long * ID_list;
public:
ClassRoom():num(0),ID_list(0){}
...
~ClassRoom(){
if(ID_list)
delete[] ID_list;
}
};
【2024.2.6快过年了。什么时候能没有压力过年... 突然意识到其实可能很长一段时间都不会轻松,或者说人生本来就是不轻松的,或者说,如果想轻松,那就不能轻松。啧啧我真是个大哲学家。今天其实跟爸妈发火了,因为他们总是在输出,向我传播焦虑,不允许我说话和表达,确实压抑挺久的了。其实每次成绩不好的时候他们总会这样焦头烂额却不自知。这给我的感觉就是,我是他们投资用来养老的商品,当看到商品股价下跌的时候,就害怕以后没有人养老了就开始不断地向我传递焦虑来迫使我回归正轨。可人生明明是旷野,又怎会是轨道。】