接上一篇文章,上一篇文章介绍了类的四种构造函数:无参、有参、拷贝、移动,这篇文章介绍其他的一些重要内容,如果有错误或遗漏,请大家批评指正。
初始化参数列表
初始化参数列表是是有参构造的一种,它可以直接初始化对象的属性,而不是给对象的属性赋值。
初始化 | 在定义一个变量的同时给它一个初值,在给值之前,还没有这个变量,不占内存,当他被定义出来之后,存储的就是这个值 |
赋值 | 给一个已经占有内存空间的变量一个值,在给值之前,这个变量已经存在,并且占用内存,他存的是其他的值 |
语法:返回值 函数名(参数列表): 属性1(参数1),属性2(参数2) ,...{函数体}
初始化参数列表在参数列表后加冒号,然后初始化的属性(要初始化的值),...后面加函数体,注意:
- 初始化参数的顺序不是按照初始化参数列表的顺序来的,就是说,不是在这个列表中先写谁就先初始化谁,而是按照类中属性的声明顺序来的,先声明谁,先初始化谁。
- 常量和引用必须使用初始化参数列表初始化
- 属性中有其他类对象,且那个类没有无参构造,需要用初始化参数列表给对应类的构造函数传参
- 只能在构造函数中使用这个语法,可以给所有的成员初始化
#include<iostream>
using namespace std;
class A {
public:
int a;
int b;
A(int num1):a(num1),b(a){}
//使用上面的构造函数,输出两个2
//A(int num1):b(num1),a(b){}
//使用这个构造函数,输出随机值和2
void display() {
cout << a << " " << b << endl;
}
};
int main() {
A a(2);
a.display();
return 0;
}
分析上面的代码,第一个构造函数,在初始化参数列表中,先初始化a,再用a初始化b,两个属性的值相同,再看第二个构造函数,初始化参数列表中先初始化b,再用b的值初始化a,结果a的值是随机值,而b的值是2。所以通过上述内容可以证明,属性的初始化与初始化参数列表的书写顺序无关,仅与类中的声明顺序有关。
类对象作为类成员
很多时候,我们的这个类(记作B)中需要包含其他类(记作A)的类对象,呢么在构造B的类对象的时候,就需要先调用A类的构造函数,来初始化A的对象,然后才能继续构造B的对象。析构的顺序则相反,先析构B类的,再析构A类的。
#include<iostream>
using namespace std;
class A{
public:
int num;
A(int num) {
this->num = num;
}
};
class B {
public:
A a;
B(int num):a(num){}
//在初始化参数列表中调用A的构造函数
void display() {
cout << a.num << endl;
}
};
int main() {
B a(2);
a.display();
return 0;
}
构造对象B时,先给B中成员a开辟空间,在初始化参数列表中调用A类的构造函数给a赋值 再调用B类的构造函数给b赋值。
析构时先调用B的析构调用A的析构 。