7.1.4 构造函数
定义:每个类都分别定义了他的对象被初始化的方式,类通过一个或几个特殊的成员函数来控制其对象的初始化过程,这些函数叫做构造函数。构造函数的任务是初始化对象的数据成员,无论何时只要类的对象被创建,就会执行构造函数。
类可以存在多个构造函数,和其他重载函数差不多,不同构造函数之间必须在参数数量或参数类型上 有所区别。
不同于其他函数构造函数不能声明成const的。
7.2 访问控制与封装
public说明符:定义在public说明符之后的成员在整个程序内可被访问。
priva说明符:定义在private说明符之后的成员可被类的成员函数访问,但是不能被使用该类的代码访问。
使用class或struct关键字
struct和class唯一的区别就是默认访问权限不同。
struct关键字:默认定义在第一个访问说明符之前的成员是public的。
class关键字:默认定义在第一个访问说明符之前的成员是privat的。
7.2.1 友元
类可以允许其他类或函数访问它的非公有成员,方法是令其它类或函数成为他的友元。如果类想把一个函数作为他的友元,只需要添加一条以friend关键字开始的函数声明语句。
注:
1.友元声明只能出现在类的内部,但是在类内出现的位置不限。
2.友元不是类的成员也不受他所在区域访问控制级别的约束。
3.一般来说最好在类定义开始或结束前的位置集中声明友元。
7.3.1 类的其他特性
定义在类内的成员函数是自动成为inline的内联函数的。
成员函数也可以重载。
可变成员函数
可以通过在变量的声明中加入mutable关键字做到。
一个可变数据成员永远不会是const,即使他是const对象的成员。
7.5 构造函数再探
7.5.1 构造函数初始值列表
构造函数的初始值有时必不可少
有时我们可以忽略初始化和赋值之间的区别,但并非总是如此。如果成员是const或者应用的话,必须将其初始化。类似的当成员属于某种类类型且该类没有定义默认构造函数时,也必须将这个成员初始化。
成员初始化的顺序
一般来说,初始化顺序没有特别要求。不过如果一个成员用另一个成员初始化,那这两个成员的初始化顺序就很关键了。
注:
尽量避免用一个成员初始化另一个成员。
如果可能得话,最好用构造函数的参数作为成员的初始值。
默认实参和构造函数
如果构造函数为所有的参数都提供了默认参数,那他实际上也定义了默认构造函数。
class Sales_data{
public:
Sales_data(string s = " "): bookNo(s){}
};
注:
是否使用默认实参构造函数要根据具体应用场景和需求确定,切记盲目使用。
7.5.4 隐式的类类型转换
explicit构造函数只能用于直接初始化
当我们使用explicit关键字声明构造函数时,他将只能以直接初始化的形式使用。
Sales_data item1(null_book);//正确:直接初始化
Sales_data item2 = null_book;//错误:拷贝初始化
7.6 类的静态成员
有时候类需要他的一些成员与类本身直接相关,而不是与类的各个对象保持关联。
声明静态成员
使用关键字static声明静态成员。
静态成员的类型可以是常量、引用、指针、类类型等。
定义静态成员
和其他成员函数一样,我们既可以在类的内部也可以在类的外部定义静态成员函数。当在类的外部定义静态成员函数时,不能重复static关键字,该关键字只能出现在类的内部的声明语句:
void Account::rate(double newRate){
interestRate = newRate;
}
注:
1.因为静态数据成员不属于类的任何一个对象,所以他们并不是在创建类的对象时被定义的。这意味着他们不是由类的构造函数初始化的。而且一般来说我们不能在类的内部初始化静态成员。相反的,必须在类的外部定义和初始化每个静态成员。和其他对象一样,一个静态成员只能被定义一次。
2.类似于全局变量,静态数据成员定义在任何函数之外。因此一旦它被定义,就将一直存在于程序的整个生命周期中。
3.要想确保对象只定义一次,最好的办法是把静态数据成员的定义与其他非内联函数的定义放在同一个文件夹中。
静态数据成员能用于某些场景,普通成员不能
1.静态成员的类型可以就是他所属的类类型。而非静态成员则受到限制,只能声明成他所属类的指针或引用。
class Bar{
private:
static Bar mem1;//正确:静态成员可以是不完全类型
Bar *mem2;//正确:指针成员可以是不完全类型
Bar mem3;//错误:数据成员必须是完全类型
}
2.我们可以使用静态成员作为默认实参,非静态成员不能作为默认实参,因为它的值本身属于对象的一部分。
class Screen{
public:
Screen& clear(char = bkground);
private:
static const char bkground;
};