第1章 面向对象编程(www.cppentry.com)
C++(www.cppentry.com)语言是一种混合型语言,一方面我们可以把C++(www.cppentry.com)当做是C语言的扩展和改进,在这种意义上,C++(www.cppentry.com)是一种过程语言;从另一方面来看,C++(www.cppentry.com)又充分展示了其面向对象的特性(这些特性都是C语言和其他过程语言所不具备的),因此,C++(www.cppentry.com)又是一种面向对象的语言。本章我们主要讨论与面向对象的编程(www.cppentry.com)风格相关的基本概念及其优点,并探讨相关的程序设计技术。以后的章节将详细讨论用C++(www.cppentry.com)语言进行面向对象程序设计的细节。
1.1 面向过程的编程(www.cppentry.com)风格与面向对象的编程(www.cppentry.com)风格
1.1.1 面向过程的编程(www.cppentry.com)风格
程序由模块(module)构成。设计程序时,可以对这些模块分别进行设计、编码和测试,最后将这些模块有机地组合在一起形成一个完整的程序。
C++(www.cppentry.com)语言由C语言发展而来。我们说C语言是一种面向过程语言(procedural language),是因为在C语言程序中,一个模块就是一个过程。在过程语言中,由于过程是由赋值语句、测试语句、过程调用等各种命令语句组成,因此有时候我们也将过程语言称为命令型语言(imperative language)。和C语言一样,C++(www.cppentry.com)语言中的函数就是过程。可以将C++(www.cppentry.com)语言当做是改进的C语言来使用。也就是说,当函数构成程序中的模块时,C++(www.cppentry.com)语言就成了一种过程语言。
面向过程程序设计通常采用自顶向下设计(top-down design)方法进行设计。在这种方法中,待解问题和程序设计语言中的过程紧密相连。例如,对于制定制造汽车任务的调度表这件事情,可将待解问题标记为MainProblem。在这里我们打算用C语言、Pascal语言这类过程语言,或者是当做过程语言使用的C++(www.cppentry.com)语言来解决上述问题。如果采用C++(www.cppentry.com)来做的话,我们很快想到可以将待解问题MainProblem对应到C++(www.cppentry.com)的过程:main。但制造汽车太复杂了,如果将所有的任务都加入到main中,MainProblem就太复杂了。常用的办法是将待解问题分解成若干子问题:
生产底盘。
生产引擎。
生产动力传动系统。
组装。
检测配件和整车。
我们可以将上述子问题分别对应到main调用的函数,即子过程。如同MainProblem可以分解成若干子问题一样,过程main也可以分解为处理子问题的各种子过程。当然这些子问题可以继续分解。这种分解就反应为子过程的分解(如图1-1所示)。不断地运用这种自顶向下设计方法,即函数分解法(functional decomposition),直到每一个子问题都足够简单,使得相应的子过程很容易处理。当采用这种高度模块化的方式来设计C++(www.cppentry.com)程序时,C++(www.cppentry.com)程序的基本过程(即函数)就会足够简单和短小,甚至可以只包含一条语句(例如,只包含一条return语句)。
自顶向下设计的优点是既直观又有条理,有很多复杂问题是采用这一方法解决的。但这种方法也有致命的缺陷,特别是在面对软件维护(software maintenance)问题时,包括软件系统的测试、调试和升级等。有经验的程序员都知道,软件开发最困难的时期并不是第一次设计代码的时候,而是后面的修改阶段,因为程序出现了毛病(“受到细菌的感染”),程序的需求发生了改变,程序需要提高执行效率,等等。我们仍然用制造汽车为例来说明这个问题。假设需要对MainProblem的解决方案进行重大改变,甚至于main都需要改动。如我们要给每一个在main中调用的子过程增加一个参数,以便传递某个额外的信息。同时每个子过程又要将这个信息传递给自己的子过程,直到如图1-1所示结构中延续到最后,这种现象就是我们熟知的串联改变。串联改变是指对某个过程(如main)的变动会传递到其子过程中,并由这些子过程继续往下延续直到所有的分解层次。这种威胁并可能愚弄维护编程(www.cppentry.com)活动!
|
| 图1-1 问题和过程的分解 |