在一定程度上学习过类与对象的人一定都知道。构造函数对于类来说,比亲儿子还亲,不论是洗澡还是上厕所他俩都是天天在一起的(雾)。就算你自己不给类自定义构造函数,编译器也会自己去调用默认的构造函数。那么构造函数到底是有怎样的魅力,才让类如此离开不了自己呢?
- 在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值。
class Date
{
public:
Date(int year, int month, int day)
{
//赋值
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
确实,构造函数这一功能非常的好啊,难怪类天天粘这它。但是只看到这里会发现一个问题,那就是某些特殊的成员变量不能初始化啊(例:const成员变量)
虽然上面程序中构造函数调用之后,对象中已经有了一个初始值,但是不能将其称为对对象中成员变量的初始化,构造函数体中的语句只能将其称为赋初值,而不能称作初始化。因为初始化只能初始化一次,而构造函数体内可以多次赋值。
一些反应快的人就会提到了:可以在定义的时候初始化啊!
class Date
{
public:
Date(int year, int month, int day)
{
//赋值
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
const int a = 10;//这是缺省值,不是初始化
};
但是,在此,我要非常遗憾地告诉你上面这种写法是缺省值,并不是预想的初始化。
那么,就没有什么办法了吗?
不不不,这时候就是初始化列表的showtime了。
初始化列表用法:
初始化列表 :以一个 冒号开始 ,接着是一个以 逗号分隔的数据成员列表 ,每个 " 成员变量 " 后面跟一个 放在括号中的初始值或表达式 。
class Date
{
public:
Date(int year, int month, int day)
: _year(year) //初始化列表
, _month(month)
, _day(day)
{
//.....
}
private:
int _year;
int _month;
int _day;
};
哈哈哈,构造函数竟然还留了这么一手,不愧是它。初始化列表虽然厉害,但是还是有几点需要注意的。
【注意】:
1. 每个成员变量在初始化列表中 只能出现一次 ( 初始化只能初始化一次 )
2. 类中包含以下成员,必须放在初始化列表位置进行初始化:
- 引用成员变量
- const成员变量
- 自定义类型成员(且该类没有默认构造函数时)
class A
{
public:
A(int a)
:_a(a)
{}
private:
int _a;
};
class B
{
public:
B(int a, int ref)
:_aobj(a) //初始化列表
, _ref(ref)
, _n(10)
{}
private:
A _aobj; //没有默认构造函数
int& _ref; //引用
const int _n; // const
};
3. 尽量使用初始化列表初始化 ,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化。
如果没有在初始化列表显示初始化:
- 内置类型,有缺省值用缺省值,没有就用随机值
- 自定义类型,调用默认它的默认构造函数,如果没有默认构造就报错
class A
{
public:
A(int a)
:_a(a)
{}
private:
int _a;
};
class B
{
public:
B()
:_n(10)
, _m(2)
, _aa(11)
{
// _n = 10;
}
private:
// const成员
const int _n; // 声明
int _m = 1; // 缺省值
A _aa;
};
4. 成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关
class A
{
public:
A(int a)
:_a1(a) //_a1初始化为1
, _a2(_a1) //_a2定义在_a1前,所以_a2先初始化,但此时_a1并未初始化为1
//所以_a1为随机值,_a2也就被初始化为随机值
{}
void Print()
{
std::cout << _a1 << " " << _a2 << std::endl;//输出‘1 随机值’
}
private:
int _a2; //_a2定义在_a1前
int _a1;
};
int main()
{
A aa(1);
aa.Print();
}
end