概述
C++构造函数之初始化列表
构造函数可以说是对于C++每个类来说最重要的组成部分,之前也详细介绍过构造函数的相关知识,今天给构造函数进行补充,主要说明一下构造函数的初始值列表
一、初始化列表的写法
仍然以之前介绍构造函数时使用的学生类来举例说明:
class Student{
public:
/*Student(int no, string name, int age){
_no = no;
_name = name;
_age = age;//带参的构造函数
}*/
Student(int no, string name, int age)
:_no(no)
,_name(name)
,_age(age)
{}//初始化列表
private:
int _no;
string _name;
int _age;
};
初始化列表出现了新的部分,以冒号开始,然后紧跟着的是以逗号为分隔符的数据成员列表,每个数据成员后面都有一个括号,括号中的是该成员变量的初始值或表达式。
二、初始化列表的注意事项
-
每个成员变量在初始化列表中只能出现一次,即初始化只会初始化一次,但是在构造函数的函数体中可以进行多次赋值,初始化与赋值的区别有一篇博客写的不错,推荐阅读:
https://www.cnblogs.com/lxy-xf/p/11049963.html
初始化的含义是创建变量时赋予它一个初始值,而赋值则是把对象的当前值擦去,用一个新值来代替!(C++primer中的描述)
-
当类中包含了:①引用成员变量;②const成员变量;③自定义类型的成员变量(该类没有自己的默认构造函数,默认构造函数详解见https://blog.csdn.net/weixin_45523353/article/details/123216917的第四部分)时,必须将这些成员放在初始化列表中进行初始化!
class A{ public: A(int a){ _a = a;//有参构造,没有默认构造函数 } private: int _a; }; class Student{ public: Student(int a, int age) :_aa(a) ,_age(age) ,_no(001) {}//必须在初始化列表中进行初始化 private: A _aa;//自定义类型,且没有自己的默认构造函数 int& _age;//引用 const int _no//const的成员变量 };
-
建议大家尽量使用初始化列表进行初始化,因为自定义类型的成员变量一定会先使用初始化列表初始化,下面这个例子可以帮助理解一下
class A { private: int _a; public: A(int a = 0) { _a = a; } }; class B { private: A _aa; int _b = 1; public: B(int a, int b) { _b = b; _aa = A(a);//B这里并没有写出初始化列表 } }; int main(){ B bb(20,15);//在这里打个断点 return 0; }
按照我们之前的理解,在创建B类型的变量bb时,使用的是B类型所提供的带参的构造函数,但是在监视窗口我们却发现,_b和_aa两个成员变量都已经被初始化了:
尽管我们没有显式地写出初始化列表,这里也认为是有初始化列表的,其中的两个成员变量会使用默认初始化列表进行初始化,可以认为初始化列表就是对象的成员变量定义的地方。
三、初始化的顺序
非常重要的地方:在初始化列表中的顺序并非成员变量的初始化顺序!,成员变量的初始化顺序只与它在类中的声明次序相同。
class A{
int a1;
int a2;
public:
A(int a)
:a2(a)
,a1(a2)
{}//这里会报编译错误
};
上面的例子虽然看起在初始化列表中先用形参a初始化a2,再用a2初始化a1,但是成员变量的初始化顺序不能看它们在初始化列表中的顺序,而要看的是声明的顺序,a1先于a2声明,因此编译器会先去初始化a1,但此时a2并没初始化,因此a1也就无法初始化了。
所以最好将初始化列表的各个成员顺序与类中的成员变量声明顺序保持一致,而且尽量不要用某个成员变量去初始化另一个成员变量!
最后
以上就是灵巧面包为你收集整理的C++构造函数之初始化列表C++构造函数之初始化列表的全部内容,希望文章能够帮你解决C++构造函数之初始化列表C++构造函数之初始化列表所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复