• 5.5 类
    • 5.5.1 用访问控制来修改Stash">5.5.1 用访问控制来修改Stash

    5.5 类

    访问控制通常是指实现细节的隐藏(implementation hiding)。将函数包含到一个结构内(常称为封装[1])来产生一种带数据和操作的数据类型,由访问控制在该数据类型之内确定边界。这样做的原因有两个:首先是决定哪些客户程序员可以用,哪些客户程序员不能用。我们可以建立结构内部的机制,而不必担心客户程序员会把内部的数据机制当做他们可使用的接口的一部分来访问。

    这就直接导出了第二个原因,那就是将具体实现与接口分离开来。如果该结构被用在一系列的程序中,而客户程序员只能对public的接口发送消息,这样就可以改变所有声明为private的成员而不必去修改客户程序员的代码。

    同时采用封装和访问控制可以防止一些情况的发生,而这在C语言的struct类型中是做不到的。现在我们已经处在面向对象编程的世界中,在这里,结构就是由对象组成的类,就像人们可以描述由鱼或鸟组成的类一样,任何属于该类的对象都将共享这些特征和行为。也就是说,结构的声明已经变成该类型的所有对象看起来像什么以及将如何行动的描述。

    在最初的面向对象编程语言Simula-67中,关键字class被用来描述一个新的数据类型。这显然启发了Stroustrup在C++中选用同样的关键字,以强调这是整个语言的关键所在。新的数据类型并非只是C中的struct加上函数,这当然需要用一个新的关键字。

    然而在C++中使用的class逐渐变成了一个非必要的关键字。它和struct的每个方面都是一样的,除了class中的成员默认为private,而struct中的成员默认为public。下面有两个结构,它们将产生相同的结果。

    5.5 类 - 图1

    5.5 类 - 图2

    在C++中,class是面向对象编程的基本概念,它是一个关键字,但本书将不再用粗体字来表示—由于总要用到“class”,都标出来会令人厌烦。类带来的变化是如此重要,因此我怀疑Stroustrup偏向于将struct重新定义,但考虑到对C的向后兼容性而没有这样做。

    许多人喜欢用一种更像struct的风格去创建一个类,因为可以通过不顾及类的“默认为private”的行为,而使用首选为public的原则。

    5.5 类 - 图3

    之所以这样做,是因为这样可以让读者首先更清楚地看到他们所要关心的成员,然后可以忽略所有声明为private的成员。事实上,所有其他成员都必须在类中声明的惟一原因是让编译器知道对象有多大,以便为它们分配合适的存储空间,并保证它们的一致性。

    但本书中的示例仍采用首先声明private成员的格式,如下例:

    5.5 类 - 图4

    有些人甚至不厌其烦地在他们的私有成员名字前加上私有标志:

    5.5 类 - 图5

    因为mX已经隐藏于Y的范围内,所以m(用它来指示成员)并不是必需的。然而在一个有许多全局变量的项目中(虽然极力想避免使用全局变量,但它们仍不可避免地在一些项目中出现),这种命名有助于在一个成员函数的定义体内识别出哪些是全局变量,哪些是成员变量。

    5.5.1 用访问控制来修改Stash

    现在把第4章的例子用类及访问控制来改写一下。请注意客户程序员的接口部分现在已经很清楚地区分开了,完全不用担心客户程序员会偶然地访问到他们不该访问的内容了。

    5.5 类 - 图6

    inflate()函数声明为private,因为它只被add()函数调用,所以它属于内部实现部分,不属于接口部分。这就意味着以后可以调整这些实现的细节,使用不同的系统来管理内存。

    在此例中,除了包含文件的名字之外,只有上面的头文件需要更改,实现文件和测试文件是相同的。

    [1]正如前面说明的一样,访问控制有时被认为是一种封装。