当一个类的成员变量是另一个类的对象时
例:
#include
using namespace std;
class A{
public:
A()
{
cout<<"A()"<x=x;
cout<<"A(int x)"<
在生成一个B的对象 B b时,如何初始化成员变量a呢?
我们知道构造函数是给对象的内存进行初始化,那么在初始化对象b的内存中a所占的内存时,应该调用类A的构造函数给a的内存进行初始化
如果将类B的构造函数定义为:
B(int x)
{
this->a=A(x);
}
运行提示:
我们的预想是用x生成的临时对象A(x)去直接生成对象b的成员变量a,应该只有A(int x)这个构造函数调用
但结果却是调用A()、A(int x)、A& operator(const A &rhs)
那我们就必须清楚初始化和赋值两者的区别:
1)初始化:一个变量或者一个对象在产生的时候就赋予一个值,属于伴随性质
2)赋值:在一个变量或者一个对象在产生之后的任意时刻赋予一个值,属于任意性质
很明显,构造函数函数体内的语句是赋值语句,而并非初始化语句
在this->a=A(x)这条语句中,A(x)调用A(int x), this->a=A(x);调用A& operator(const A &rhs)
那么 A()这个函数应该在构造函数B(int x)运行前就被调用。
那么我们如何直接利用临时对象A(x)去直接生成对象b的成员变量a呢?
那就利用到了构造函数的初始化列表
它的作用:对数据成员进行初始化
构造函数的初始化列表格式:构造函数():变量名1(数值),变量名2(数值)
例:
B(int x):a(x)
{
}
将成员对象a放在构造函数的初始化列表中,运行结果:
从结果可知,在初始化列表中的变量直接初始化,而并非赋值。
初始化列表的特点:
1)在构造函数执行时,先执行初始化列表,实现变量的初始化,然后再执行构造函数内部的语句进行赋值操作。
例:
#include
using namespace std;
class A{
public:
A(int a,int b,int c):x(a),y(b),z(c)
{
cout<<"A(int a,int b,int c)"<
运行结果:
2)成员初始化的顺序只与声明的顺序有关,而跟初始化列表的顺序无关。例如在上面的代码中类A的构造函数初始化列表中,我们写成:z(x),y(x), x(a),但是我们还是先初始化变量x,然后y,然后z,因为我们先声明的变量a,然后b,然后c
例:
#include
using namespace std;
class A{
public:
A(int a,int b,int c):y(x),z(x),x(a)
{
cout<<"A(int a,int b,int c)"<
运行结果:
如果按照初始化列表中y(x),z(x),x(a)的顺序进行初始化,结果应该为x=1,y=0xcccccccc,z=0xcccccccc.
但我们从运行结果可以看出,x,y,z的值都为1,那么它初始化的顺序就不按照初始化列表的顺序进行初始化,
而根据变量的声明顺序进行初始化。
3)成员之间可以相互初始化:a(12), b(a) //a,b为相同类型的话
从上面代码y(x),z(x),x(a)就可以看出。
从上面的代码我们可以看出,内置类型的变量可以在构造函数的函数体内进行赋值,可以直接在构造函数的初始化列表中直接初始化,那么什么样的数据必须放到构造函数的初始化列表中呢?
1)const修饰的成员变量。
我们知道,在C++中const修饰的变量称之为常量,它一定要初始化,并且常量是不能进行修改的,
而构造函数的函数体内语句是进行赋值操作,如果将const修饰的成员变量的放到构造函数的函数体内进行赋值,
这就明显修改常量内存块的值,代码错误。
2)引用类型的成员变量。
我们知道,在C++中引用一定要初始化,并且引用不能修改,
如果放到构造函数的函数体内进行赋值,修改引用所引用的变量,代码错误。