C++:类和对象 III(初始化列表、explicit、友元、匿名对象)
目录
初始化列表
初始化列表的特点
类型转换、explicit
隐式类型转换
explicit关键字
static成员
静态成员变量
静态成员函数
友元
友元函数
友元类
内部类
匿名对象
编译器优化
初始化列表
初始化列表就是类成员初始化的地方
函数有它声明和定义的地方,变量也有,类成员也有
先来看看日期类的默认构造函数
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1(2024, 7, 15);
return 0;
}
在类里面显示出来的成员我们把它叫做声明
如果你认为我们就这样把_year,_month,_day给初始化了,那就错了
这并不是初始化,这是赋值
如果我们要初始化类成员的话应该这样做
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
:_year(year)
,_month(month)
,_day(day)
{}
private:
int _year;
int _month;
int _day;
};
这一块就是初始化列表
先是一个冒号开始,然后以逗号分隔,成员变量后面跟初始值或者表达式
这样我们就完成了一个成员的定义和初始化
那么这两种写法有什么区别呢?
这两种写法给我们带来的效果都是一样的,但是无论怎么写我们的成员变量都要经过初始化列表一遍,就算没有写初始化列表也会!所以这里建议尽量使用初始化列表初始化
如果我们不知道初始化列表怎么给,我们可以在声明的地方给一个缺省值,例如:
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
:_year(year)
,_month(month)
,_day(day)
{}
private:
int _year = 1900;
int _month = 1;
int _day = 1;
};
这样就算我们没有写初始化列表也会给我们自动初始化上这些值
注意:
const成员变量,带引用的成员变量,只有一次初始化的机会!那就是在初始化列表中!
class A
{
public:
A(int a = 1)
{
_a = a;
}
private:
const int _a;
};
因为const常量不能被赋值,只能在初始化的地方被初始化,正确代码如下:
class A
{
public:
A(int a = 1)
:_a(a)
{}
private:
const int _a;
};
class A
{
public:
A(int a = 1)
:_a(a)
{}
private:
int& _a;
};
初始化列表的特点
如果我们没有在声明的地方给缺省值,也没有写初始化列表,那么值由编译器决定
如果我们给了缺省值没有写初始化列表,那么会根据缺省值初始化
如果我们即给了缺省值也给了初始化列表,那么根据初始化列表的值初始化
注:上述行为于构造函数内部行为无关
初始化列表中按照成员在类中声明的定义来初始化,于初始化列表中出现的先后顺序无关
例如:
class A
{
public:
A()
:_a(1)
, _b(_a)
{}
//private:
int _b;
int _a;
};
int main()
{
A a;
cout 


