一、什么是初始化列表
与其他函数不同,构造函数除了有名字,参数列表和函数体之外,还可以有初始化列表,初始化列表以冒号开头,后跟一系列以逗号分隔的初始化字段
二、构造函数执行分为初始化和构造两个阶段,且初始化化阶段优先于计算阶段
三、一个好的原则是,能使用初始化列表的时候尽量使用初始化列表
因为初始化列表有时能少调用一次默认构造函数
四、必须要用初始化列表的时候
1.常量成员,因为常量只能初始化不能赋值,所以必须放在初始化列表里面
2.引用类型,引用必须在定义的时候初始化,并且不能重新赋值,所以也要写在初始化列表里面
3. 没有默认构造函数的类类型,因为使用初始化列表可以不必调用默认构造函数来初始化,而是直接调用拷贝构造函数初始化
五 、成员变量是按照在类中声明的顺序被初始化的而不是在初始化列表中的顺序
struct foo
{
int i ;int j ;
foo(int x):i(x), j(i){}; // ok, 先初始化i,后初始化j
};
再看下面的代码:
struct foo
{
int i ;int j ;
foo(int x):j(x), i(j){} // i值未定义
};
这里i的值是未定义的因为虽然j在初始化列表里面出现在i前面,但是i先于j定义,所以先初始化i,而i由j初始化,此时j尚未初始化,所以导致i的值未定义。一个好的习惯是,按照成员定义的顺序进行初始化。
六、含有参数的继承类的初始化
代码1如下:
1 // 集成类的初始化实验.cpp : 定义控制台应用程序的入口点。 2 // 3 4 #include "stdafx.h" 5 #include<iostream> 6 using namespace std; 7 8 class A 9 { 10 public: 11 int a,b; 12 char c; 13 A(int a1,int b1,char c1) 14 { 15 a=a1; 16 b=b1; 17 c=c1; 18 } 19 virtual ~A(){} 20 }; 21 22 class B:public A 23 { 24 public: 25 int d; 26 B(int a2,int b2,char c2,int d2):A(a2,b2,c2) 27 { 28 d=d2; 29 } 30 virtual~B(){} 31 }; 32 int _tmain(int argc, _TCHAR* argv[]) 33 { 34 B b=B(1,2,'a',3); 35 cout<<b.a<<endl<<b.b<<endl<<b.c<<endl<<b.d; 36 return 0; 37 }
从执行结果上看,好像是将34行中B b=B(1,2,3,'a');的1,2,3,'a'依次赋值给26行中B(int a2,int b2,char c2,int d2):A(a2,b2,c2)的a2,b2,c2,d2,然后在将a2,b2,c2,依次赋值给13行中A(int a1,int b1,char c1) 的a1,b1,c1
将代码改变一下:
1 // 集成类的初始化实验.cpp : 定义控制台应用程序的入口点。 2 // 3 4 #include "stdafx.h" 5 #include<iostream> 6 using namespace std; 7 8 class A 9 { 10 public: 11 int a,b; 12 char c; 13 A(int a1,int b1,char c1) 14 { 15 a=a1; 16 b=b1; 17 c=c1; 18 } 19 virtual ~A(){} 20 }; 21 22 class B:public A 23 { 24 public: 25 int d; 26 B(int a2,int b2,int d2,char c2):A(a2,b2,c2) 27 { 28 d=d2; 29 } 30 virtual~B(){} 31 }; 32 int _tmain(int argc, _TCHAR* argv[]) 33 { 34 B b=B(1,2,3,'a'); 35 cout<<b.a<<endl<<b.b<<endl<<b.c<<endl<<b.d; 36 return 0; 37 }
从执行结果上看,并没有将d2的值3直接赋值给c2(c1),所以并不是按顺序依次赋值,而是先自动找好类型,然后按照类型顺序依次赋值的。
声明:本文部分内容摘自百度百科