class
或关键字struct
来定义,语法如下:class class_name { access_specifier_1: member1; access_specifier_2: member2; ... } object_names; |
class_name
是类的有效标识符,object_names
是此类的对象的名称的可选列表。声明的体可以包含成员,这些成员可以是数据声明或函数声明,还可以包含可选的访问说明符。private
、public
或protected
。这些说明符会修改它们后面的成员的访问权限。private
成员只能从同一类的其他成员(或其“朋友”)内部访问。protected
成员可以从同一类的其他成员(或其“朋友”)访问,也可以从其派生类的成员访问。public
成员可以在任何可见对象的地方访问。class
关键字声明的类的所有成员都具有私有访问权限。因此,在任何其他访问说明符之前声明的任何成员都自动具有私有访问权限。例如:
|
|
Rectangle
的类(即类型),以及该类的一个名为rect
的对象(即变量)。该类包含四个成员:两个int
类型的数据成员(成员width
和成员height
),具有私有访问权限(因为私有是默认的访问级别),以及两个具有公共访问权限的成员函数:函数set_values
和area
。目前我们只包含了它们的声明,而没有包含它们的定义。Rectangle
是类名(即类型),而rect
是Rectangle
类型的对象。这与以下声明中的int
和a
的关系相同:
|
|
int
是类型名(类),a
是变量名(对象)。Rectangle
和rect
之后,对象rect
的任何公共成员都可以像访问普通函数或普通变量一样进行访问,只需在对象名和成员名之间插入一个点(.
)即可。这与访问普通数据结构的成员的语法相同。例如:
|
|
rect
中唯一不能从类外部访问的成员是width
和height
,因为它们具有私有访问权限,只能在该类的其他成员内部引用。Rectangle
类的完整示例:
|
|
area: 12 |
::
,两个冒号),该运算符在前面章节中与命名空间相关。此处用于在类外部定义类的成员函数set_values
。area
的定义已直接包含在类Rectangle
的定义中,因为其极其简单。相反,set_values
仅在类中用其原型声明,但其定义在类外部。在此外部定义中,使用作用域运算符(::
)来指定正在定义的函数是Rectangle
类的成员,而不是常规的非成员函数。::
)指定了正在定义的成员所属的类,提供了与将此函数定义直接包含在类定义中完全相同的范围属性。例如,上例中的函数set_values
可以访问变量width
和height
,它们是Rectangle
类的私有成员,因此只能从该类的其他成员(例如这个函数)访问。width
和height
具有私有访问权限(请记住,如果没有指定其他内容,使用class
关键字定义的类的所有成员都具有私有访问权限)。通过将它们声明为私有,不允许从类外部访问。这是有意义的,因为我们已经定义了一个成员函数来为对象中的这些成员设置值:成员函数set_values
。因此,程序的其余部分不需要直接访问它们。也许在这个如此简单的例子中,很难看出限制对这些变量的访问有何用处,但在更大的项目中,防止值以意外的方式(从对象的角度来看是意外的)修改可能非常重要。Rectangle
类的先前示例为例,我们可以除了对象rect
之外,还可以声明对象rectb
:
|
|
rect area: 12 rectb area: 30 |
Rectangle
,它有两个实例(即对象):rect
和rectb
。它们中的每一个都有自己的成员变量和成员函数。rect.area()
的结果与调用rectb.area()
的结果不同。这是因为Rectangle
类的每个对象都有自己的变量width
和height
,因为它们(以某种方式)也有自己的函数成员set_value
和area
,这些函数作用于对象自己的成员变量。rect.area
或rectb.area
时没有传递任何参数。这些成员函数直接使用了它们各自对象rect
和rectb
的数据成员。set_values
之前调用成员函数area
会发生什么?结果不确定,因为成员width
和height
从未被赋值。void
。Rectangle
类可以通过实现构造函数来轻松改进:
|
|
rect area: 12 rectb area: 30 |
Rectangle
类没有成员函数set_values
,而是有一个构造函数执行类似的操作:它使用传递给它的参数来初始化width
和height
的值。
|
|
void
:构造函数从不返回值,它们只是初始化对象。
|
|
rect area: 12 rectb area: 25 |
Rectangle
类的对象:rect
和rectb
。rect
使用两个参数构造,如之前的示例所示。rectb
调用了默认构造函数。请注意,rectb
甚至没有用一对空括号构造——实际上,空括号不能用于调用默认构造函数。
|
|
rectc
声明为函数,而不是对象声明:它将是一个不接受任何参数并返回Rectangle
类型值的函数。class_name object_name = initialization_value;
{}
)而不是圆括号(()
):class_name object_name { value, value, value, ... }
|
|
foo's circumference: 62.8319 |
|
|
initializer_list
作为其类型的偏好。:
)和类成员的初始化列表来完成的。例如,考虑一个具有以下声明的类:
|
|
|
|
|
|
|
|
|
|
foo's volume: 6283.19 |
Cylinder
类有一个成员对象,其类型是另一个类(base
的类型是Circle
)。由于Circle
类的对象只能通过参数构造,因此Cylinder
的构造函数需要调用base
的构造函数,而唯一的方法是在成员初始化列表中进行。{}
)而不是圆括号(()
):
|
|
|
|
Rectangle
类对象的指针。->
)从指针直接访问对象成员。以下是一个包含一些可能组合的示例:
|
|
*
、&
、.
、->
、[]
)。它们可以解释为:表达式 | 可以读作 |
---|---|
*x | x 指向的对象 |
&x | x 的地址 |
x.y | 对象x 的成员y |
x->y | 指向x 的对象成员y |
(*x).y | 指向x 的对象成员y (与上一行等效) |
x[0] | x 指向的第一个对象 |
x[1] | x 指向的第二个对象 |
x[n] | x 指向的第(n+1) 个对象 |
[]
),而普通数据结构章节介绍了箭头运算符(->
)。class
定义,还可以使用关键字struct
和union
定义。struct
通常用于声明普通数据结构,但也可以用于声明具有成员函数的类,语法与关键字class
相同。两者之间的唯一区别是,使用关键字struct
声明的类的成员默认具有public
访问权限,而使用关键字class
声明的类的成员默认具有private
访问权限。在所有其他方面,在这方面这两个关键字是等效的。struct
和class
定义的类不同,因为联合一次只能存储一个数据成员,但尽管如此,它们也是类,因此也可以包含成员函数。联合类中的默认访问权限是public
。![]() 其他数据类型 | ![]() 目录 | ![]() 类 (II) |