9.2 类的成员
类描述 :
成员声明 类描述 opt
访问描述符 : 类描述 opt
成员声明 :
声明描述符序列 opt 成员声明器列表 opt ;
函数定义 ; opt
:: opt 嵌套名字声明 template opt 未限定的标识符 ;
using- 声明
模板声明
成员声明器列表 :
成员声明器
成员声明器列表 , 成员声明器
成员声明器 :
声明符 纯虚描述符 opt
声明符 常量初始化器 opt
标识符 opt : 常量表达式
纯虚描述符 :
= 0
常量初始化器 :
= 常量表达式
1. 类定义中的类描述声明了该类的全部成员。其他任何地方都不能再插入成员。类的成员包括:数据成员、成员函数、嵌套类型、枚举器。数据成员和成员函数包括静态和非静态的;嵌套类型包括类中定义的类和枚举。类中定义的枚举类型的枚举器是类的成员。除了用来声明友元或引入基类的成员名字,成员声明声明了类的成员,并且每个成员的声明都声明至少一个类的成员。类的类描述中,每个成员不能声明 2 次,除非是嵌套类或成员类模板可以被先声明然后再定义。
2. 在类描述符的结尾 } 处,类被看做一个已完全定义好的对象类型(即完整类型)。在类的类描述之内,类在函数体、默认参数和构造函数的构造初始化器(包括嵌套类的这些东西)中被认为是完整类型。否则,在类描述之内它会被当做不完整类型。
3. 【注:如果参数不同,一个名字可以用来表示多个成员函数。】
4. 只有当声明一个静态整型常量或枚举常量的时候,成员声明器中才可以包含常量初始化器。
5. 成员可以使用构造函数来初始化。
6. 成员不能是 auto 、 extern 、 register 类型。
7. 声明描述符序列只能在构造函数、析构函数和类型转换函数中省略。成员声明列表只能在带 friend 关键字的类描述符、枚举描述符、声明描述符序列之后省略。纯虚描述符只能在虚函数的声明中使用。
8. 非静态成员如果是某个类的对象,那么这个类应该在先前就已经定义好。特别的是,类 cl 不能包含 cl 类型的对象,但是可以包含 cl 类型的指针或引用。当数组作为非静态成员的类型时,其所有的维度都必须指定大小。
9. 除了构造指针的指针、该类(或其派生类)的非静态成员函数中、该类(或其派生类)的构造函数的成员初始化器中,类的非静态数据成员或成员函数只能用类成员访问语法来表示。
10. 【注:非静态成员函数是个普通的函数类型,非静态数据成员是个普通的对象类型。没有特殊的成员函数类型或数据成员类型。】
11. 【例:一个简单的类定义如下:
struct tnode {
char tword[20];
int count;
tnode *left;
tnode *right;
};
包含了一个 20 字符的数组,一个整数,两个指向相似结构的指针。一旦这样定义了,
tnode s, *sp;
将 s 声明为一个 tnode 类型的结构, sp 是一个指向 tnode 类型的指针。这些声明, sp->count 表示 sp 指针指向的对象的 count 成员; s.left 表示结构 s 的左子树指针; s.right->tword[0] 表示 s 的右子树的 tword 成员的第一个字符。】
12. 声明了没有干扰的访问描述符的(非联合的)类,它的非静态数据成员被分配空间,这样后面的成员在类对象内部有更高的地址。被访问描述符隔开的非静态数据成员的空间分配顺序是未定义的。实现地址对齐的需求会导致两个相邻的成员不一定紧接着分配空间;管理虚函数和虚基类的需求也一样。
13. 如果 T 是类的名字,下列实体的名字必须与 T 不同:
a) T 的每个静态数据成员
b) T 的每个成员函数【注:不包括构造函数,因为它没有名字。】
c) T 的每个类型成员
d) T 的每个枚举类型成员的枚举器
e) T 的每个匿名联合成员
13a 除此之外,如果 T 有一个用户定义的构造函数,那么 T 的每个非静态数据成员的名字都不能与 T 相同。
14. 如果两个平凡结构有相同数量的非静态成员,且对应的非静态数据成员的内存布局依次兼容,那么这两个结构的内存布局就是兼容的。
15. 如果两个平凡联合有相同数量的非静态成员,且对应的非静态数据成员的内存布局依次(如果有序的话)兼容,那么这两个结构的内存布局就是兼容的。
16. 如果一个平凡联合包含两个或多个共享同一初始序列的平凡结构,并且该平凡联合对象当前包含这些平凡结构之一,那么就可以通过其中任意一个平凡结构来访问共享的初始序列部分。如果两个平凡结构的一个或多个起始成员的相应内存布局兼容(对位域来说要有相同的宽度),那么它们俩共享一个初始序列。
17. 指向平凡类型的指针,经过用 reinterpret_cast 合适地转换,指向它的起始成员(如果该成员是位域,就只想它所在的存储单元);反之亦然。【注:因此,在平凡结构对象内部就可能因为制造合适的对齐而形成无名填充区,但该区肯定不能在对象的起始处。】