思考c++编程
理想的状态下,你完成一个程序设计任务分为三步。第一,你必须清楚的理解问题(分析analysis),然后,你要定义在解决方案中关键的概念(设计design),最后,你必须以程序的方式表达出解决方案(编程programming)。然而,解决方案中的问题和(关键)概念只有通过在程序中努力的表达和运行程序的结果才能够清晰的表达,这就是选择编程语言的麻烦之处。
在大部分程序中,有一些(关键)概念不能够容易的通过基础类型或不联系数据的函数来表达。给出这样一个概念,可以在程序中用声明的一个类来表达它。一个c++类是一种类型(type),它指出类的实例有怎样的动作:它们怎样被创建,它们怎样被操作,它们怎样被销毁。类还可以指出对象(类的实例)怎样表现,虽然在程序设计的早期它将不是主要的部分。写一个好的程序的关键是设计一个好的类,它能够清楚的表达出一个单独的概念(concept).这意味这你经常的关注于(focus on)下面的问题上:这个类的对象(实例)怎样被创建?类的对象(实例)能被拷贝或者销毁吗?什么运算符能够被应用到这个对象上?如果对于这些问题没有一个好的回答,那么也许概念(concept)不是清晰的。用更多的考虑问题和计划解决方案来代替立即开始编码也许是一个很好的主意.
最容易应付的概念是那些已经有了传统的数学模式的:数字的排序,集合,几何图形等等。面向字符的I/O,字符串,基本的容器,在这些容器上的基本的算法,和一些数学运算类是c++标准类库的一部分。此外,乱七八糟的各式各样的支持普遍的和特殊领域的类库也是可用的。
一个概念(concept)不可能凭空存在,它总是集合一组有联系的概念(concept),类之间的联系由程序组织在一起,就是解决方案中不同概念之间确实存在的联系,这经常要比开始是摆放单独的类要困难的多。最好不要使类的依赖(depend on)关系很复杂。假设两个类A和B,象"A调用B的函数","A创建B"和"B是A的成员"这样的关系是很少导致严重的错误的。但是象"A使用了B的成员变量"这样的最好被排除。
管理复杂的最有力的智能工具之一是继承命令,也就是组织一组相联系的概念(concept)到一个树状结构中,最一般(general)的概念(concept)作为根。在c++中,派生类以这样的结构表达。一个程序经常被组织为一些树的集合或者非循环的类图。就是程序员指定一些基类,每个类都有派生出的子类。虚函数经常被用来定义基类的操作。当必要的时候,这些操作的解释能被重新定义在子类之中。
有的时候一个直接的非循环类图不是足够的组织一个程序里的概念(concept);有些概念看起来天生的互相依赖.在这种情况下,我们努力的局部化这些循环的依赖,使它们不影响整个的程序结构。如果你不能排除或者局部化这些固有的依赖关系,你将很可能陷入这些困境,没有编程语言可以帮助你出来。除非你能想象一些基类(base concept)之间的容易规定的关系(easily stated relationships)。否则程序将变得不可管理。
解开依赖关系的最好的一个工具就是将接口和实现清楚的分离开。抽象类是c++这么做的主要工具。
另一种通用的形式可以用模板来表达,一个类模板可以指定一族(a family of)类。例如,一个列表(list)的模板指定“类T的列表”,类T可以是任何类。因而,模板是这样一种装置,它指定一种类型怎样被作为参数的另一种类型替代。最一般的模板是一些容器类,象列表(lists),数组(arrays),联合数组(associative arrays)和用在这些容器上的最基本的算法。如果使用继承表达将一个类作为类或者函数的参数有错误的话,最好使用模板来做。
记得许多程序能使用原始的类型,数据结构,简单的函数和很少的类库,清楚而简单的完成。可以不定义新的类型,除非它(定义新类型)是真的必要。
问题"怎样写好的c++程序?"和问题"怎样用英语写好的散文?"是很相似的。有两个问题:"知道你想说什么"和"实践,模仿好的写法",这两个问题是对于写英语散文的,它们同样适用于写c++程序,做起来也是同样难的。