- 编译器分两步处理类:首先编译成员的声明,直到类全部可见后才编译函数体,因此,成员函数体可以随意使用类中的其他成员而无需在意这些成员出现的次数
- 将const写在成员函数的参数列表后的函数称为常量成员函数,常量成员函数不改变调用它的对象的内容;常量对象,以及常量对象的引用或指针都只能调用常量成员函数
编译器创建的构造函数又称为合成的默认构造函数,合成的构造函数只适用于非常简单的类,对于大多数类来说,这个合成的默认构造函数将按照如下规则初始化类的数据成员
- 如果存在类内的初始值,用它来初始化成员
- 否则,默认初始化该成员
- 初始化变量以及以值的方式传递或返回一个对象时对象会被拷贝;使用赋值运算符时会发生对象的赋值操作
- class 与 struct唯一的区别是默认访问权限不太一样,使用struct时,定义在第一个访问说明符(public,private,protected)之前的成员是public的,class是private的
- 友元声明只能出现在类定义的内部,具体为止不限,友元不是类的成员,不受它所在区域访问控制级别的约束,一般来说,最好在类定义开始时或者结束前集中声明友元;友元声明仅仅指定了访问权限,而非一个通常意义上的函数声明
- 类可以自定义某种类型在类中的别名,用来定义类型的成员必须先定义后使用
- 可变数据成员:声明时加入mutable关键字,我们有时希望在一个const成员函数中修改这个数据成员,可变数据成员永远不会是是const
必须首先完成类的定义,然后编译器才知道存储该数据成员需要多少空间,因为只有当类全部完成后类才算被定义,所以一个类的成员类型不能是该类自己。然而,一旦一个类的名字出现后,它就被认为是声明过了(但未被定义),因为类允许包含指向它自身类型的引用或指针
class Link_screen{ Screen window; Link_screen *next; Link_screen *prev; };
如果一个类指定了友元类,则友元类的成员函数可以访问此类包括非共有成员在内的所有成员,当把一个成员函数声明为友元时,必须明确指出该成员函数属于哪个类;如果一个类想把一组重载函数声明成它的友元,它需要对这组函数中的每一个分别声明;友元函数可以定义在类的内部,即使在类的内部定义该友元函数,我们也必须在类的外部提供相应的声明使得该函数可见
struct X{ friend void f() { std::cout << "友元函数可以定义在类的内部" << std::endl;} //X() { f(); } // 错误:f还没有被声明 void g(); void h(); }; //void X::g() { return f(); } //错误:f还没有被声明 void f(); void X::h() { return f(); } //正确
- 我们初始化const或者引用类型的唯一机会就是通过构造函数初始值(不能赋赋值)
- 成员的初始化顺序与他们在类定义中的出现顺序一致,与构造函数初始值列表中初始值的前后顺序无关;尽量避免使用某些成员初始化某些成员,这样我们就不必考虑成员的初始化顺序
- 委托构造函数把自己的一些(或者全部)职责委托给了其他的构造函数,受委托的构造函数的初始值列表和函数体依次执行,然后控制权才会交给委托者的函数体
- 编译器只会自动地执行一步类型转换,使用关键字 explicit 阻止构造函数定义的隐式转换,关键字只对一个实参的构造函数有效,需要多个实参的构造函数不能用于执行隐式转换,所以无需将这些函数指定为explicit的,explicit关键字只允许出现在类内的构造函数声明处;我们可以使用explicit构造函数显式进行强制类型转换
聚合类:
- 所有成员都是public的
- 没有定义任何构造函数
- 没有类内初始值
- 没有基类,也没有virtual函数
struct Data{ int ival; string s; };
我们可以提供一个用花括号括起来的成员初始值列表来初始化聚合类数据成员,若初始值列表元素少于类的数据成员数量,则靠后的成员被值初始化
16.关于静态数据成员:
(1)不能声明为const的;
(2)不与任何对象绑定在一起,不包含this指针;
(3)可以使用作用域运算符,类的对象、引用或指针来访问;
(4)必须在类外部定义和初始化每一个静态成员,一个静态数据成员只能定义一次;
(5)我们可以为静态成员提供const整数类型的类内初始值,不过要求静态成员必须式字面值常量类型的constexpr,初始值必须是常量表达式
(6)可以使用静态成员作为默认实参
c++ primer 笔记,第七章
最新推荐文章于 2018-08-10 15:43:34 发布