C++编程思想01.pdf
《C++编程思想01.pdf》由会员分享,可在线阅读,更多相关《C++编程思想01.pdf(21页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、下载第1章对象的演化计算机革命起源于一台机器,程序设计语言也源于一台机器。然而计算机并不仅仅是一台机器,它是心智放大器和另一种有表述能力的媒体。这一点使它不很像机器,而更像我们大脑的一部分,更像其他有表述能力的手段,例如写作、绘画、雕刻、动画制作或电影制作。面向对象的程序设计是计算机向有表述能力的媒体发展中的一部分。本章将介绍面向对象程序设计(O O P)的基本概念,然后讨论O O P开发方法,最后介绍使程序员、项目和公司使用面向对象程序设计方法而采用的策略。本章是一些背景材料,如果读者急于学习这门语言的具体内容,可以跳到第 2章,然后再回过头来学习本章。1.1 基本概念C+包含了比面向对象程
2、序设计基本概念更多的内容,读者应当在学习设计和开发程序之前先理解该语言所包含的基本概念。1.1.1 对象:特性+行为1第一个面向对象的程序设计语言是 6 0年代开发的S i m u l a-6 7。其目的是为了解决模拟问题。典型的模拟问题是银行出纳业务,包括出纳部门、顾客、业务、货币的单位等大量的“对象”。把那些在程序执行期间除了状态之外其他方面都一样的对象归在一起,构成对象的“类”,这就是“类”一词的来源。类描述了一组有相同特性(数据元素)和相同行为(函数)的对象。类实际上就是数据类型,例如,浮点数也有一组特性和行为。区别在于程序员定义类是为了与具体问题相适应,而不是被迫使用已存在的数据类型
3、。这些已存在的数据类型的设计动机仅仅是为了描述机器的存储单元。程序员可以通过增添他所需要的新数据类型来扩展这个程序设计语言。该程序设计系统欢迎创建、关注新的类,对它们进行与内部类型一样的类型检查。这种方法并不限于去模拟具体问题。尽管不是所有的人都同意,但大部分人相信,任何程序都模拟所设计系统。O O P技术能很容易地将大量问题归纳成为一个简单的解,这一发现产生了大量的O O P语言,其中最著名的是S m a l l t a l kC+之前最成功的O O P语言。抽象数据类型的创建是面向对象程序设计中的一个基本概念。抽象数据类型几乎能像内部类型一样准确工作。程序员可以创建类型的变量(在面向对象程
4、序设计中称为“对象”或“实例”)并操纵这些变量(称为发送“消息”或“请求”,对象根据发来的消息知道需要做什么事情)。1.1.2 继承:类型关系类型不仅仅说明一组对象上的约束,还说明与其他类型之间的关系。两个类型可以有共同的特性和行为,但是,一个类型可能包括比另一个类型更多的特性,也可以处理更多的消息1 这一描述部分引自我对The Tao of Objects(Gary Entsminger著)一书的介绍。(或对消息进行不同的处理)。继承表示了基本类型和派生类型之间的相似性。一个基本类型具有所有由它派生出来的类型所共有的特性和行为。程序员创建一个基本类型以描述系统中一些对象的思想核心。由这个基本
5、类型派生出其他类型,表达了认识该核心的不同途径。例如,垃圾再生机要对垃圾进行分类。这里基本类型是“垃圾”,每件垃圾有重量、价值等等,并且可以被破碎、融化或分解。这样,可以派生出更特殊的垃圾类型,它们可以有另外的特性(瓶子有颜色)或行为(铝可以被压碎,钢可以被磁化)。另外,有些行为可以不同(纸的价值取决于它的种类和状态)。程序员可以用继承建立类的层次结构,在该层次结构中用类型术语来表述他需要解决的问题。第二个例子是经典的形体问题,可以用于计算机辅助设计系统或游戏模拟中。这里基本类型是“形体”,每个形体有大小、颜色、位置等。每个形体能被绘制、擦除、移动、着色等。由此,可以派生出特殊类型的形体:圆、
6、正方形、三角形等,它们中的每一个都有另外的特性和行为,例如,某些形体可以翻转。有些行为可以不同(计算形体的面积)。类型层次结构既体现了形体间的类似,又体现了它们之间的区别。用与问题相同的术语描述问题的解是非常有益的,这样,从问题描述到解的描述之间就不需要很多中间模型(程序语言解决大型问题,就需要中间模型)。面向对象之前的语言,描述问题的解不可避免地要用计算机术语。使用对象术语,类型层次结构是主要模型,所以可以从现实世界中的系统描述直接进入代码中的系统描述。实际上,使用面向对象设计,人们的困难之一是从开始到结束过于简单。一个已经习惯于寻找复杂解的、训练有素的头脑,往往会被问题的简单性难住。1.1
7、.3 多态性当处理类型层次结构时,程序员常常希望不把对象看作是某一特殊类型的成员,而把它看作基本类型成员,这样就可以编写不依赖于特殊类型的代码。在形体例子中,函数可以对一般形体进行操作,而不关心它们是圆、正方形还是三角形。所有的形体都能被绘制、擦除和移动,所以这些函数能简单地发送消息给一个形体对象,而不考虑这个对象如何处理这个消息。这样,新添类型不影响原来的代码,这是扩展面向对象程序以处理新情况的最普通的方法。例如,可以派生出形体的一个新的子类,称为五边形,而不必修改那些处理一般形体的函数。通过派生新子类,很容易扩展程序,这个能力很重要,因为它极大地减少了软件维护的花费。(所谓“软件危机”正是
8、由软件的实际花费远远超出人们的想象而产生的。)如果试图把派生类型的对象看作它们的基本类型(圆看作形体,自行车看作车辆,鸬鹚看作鸟),就有一个问题:如果一个函数告诉一个一般形体去绘制它自己,或者告诉一个一般的车辆去行驶,或者告诉一只一般的鸟去飞,则编译器在编译时就不能确切地知道应当执行哪段代码。同样的问题是,消息发送时,程序员并不想知道将执行哪段代码。绘图函数能等同地应用于圆、正方形或三角形,对象根据它的特殊类型来执行合适的代码。如果增加一个新的子类,不用修改函数调用,就可以执行不同的代码。编译器不能确切地知道执行哪段代码,那么它应该怎么办呢?在面向对象的程序设计中,答案是巧妙的。编译器并不做传
9、统意义上的函数调用。由非O O P编译器产生的函数调用会引起与被调用代码的“早捆绑”,对于这一术语,读者可能还没有听说过,因为从来没有想到过它。早捆绑意味着编译器对特定的函数名产生调用,而连接器确定调用执行代码的绝对地址。对于 O O P,在程序运行之前,编译器不确定执行代码的地址,所以,当消息发送给一般对象时,需要采用其他的方案。为了解决这一问题,面向对象语言采用“晚捆绑”的思想。当给对象发送消息时,在程序2C+编程思想下载运行之前不去确定被调用的代码。编译器保证这个被调用的函数存在,并完成参数和返回值的类型检查,但是它不知道将执行的准确代码。为了实现晚捆绑,编译器在真正调用的地方插入一段特
10、殊的二进制代码。通过使用存放在对象自身中的信息,这段代码在运行时计算被调用函数的地址(这一问题将在第 1 4章中详细介绍)。这样,每个对象就能根据一个指针的内容有不同的行为。当一个对象接收到消息时,它根据这个消息判断应当做什么。程序员可以用关键字 v i r t u a l表明他希望某个函数有晚捆绑的灵活性,而并不需要懂得v i r t u a l的使用机制。没有它,就不能用 C+做面向对象的程序设计。Vi r t u a l函数(虚函数)表示允许在相同家族中的类有不同的行为。这些不同是引起多态行为的原因。1.1.4 操作概念:OOP程序像什么我们已经知道,用C 语言编写的过程程序就是一些数据
11、定义和函数调用。要理解这种程序的含义,程序员必须掌握函数调用和函数实现的本身。这就是过程程序需要中间表示的原因。中间表示容易引起混淆,因为中间表示的表述是原始的,更偏向于计算机,而不偏向于所解决的问题。因为 C+向 C 语言增加了许多新概念,所以程序员很自然地认为,C+程序中的m a i n()会比功能相同的 C 程序更复杂。但令人吃惊的是,一个写得很好的C+程序一般要比功能相同的C程序更简单和容易理解。程序员只会看到一些描述问题空间对象的定义(而不是计算机的描述),发送给这些对象的消息。这些消息表示了在这个空间的活动。面向对象程序设计的优点之一是通过阅读,很容易理解代码。通常,面向对象程序需
12、要较少的代码,因为问题中的许多部分都可以用已存在的库代码。1.2 为什么C+会成功C+能够如此成功,部分原因是它的目标不只是为了将 C语言转变成O O P语言(虽然这是最初的目的),而且还为了解决当今程序员,特别是那些在 C语言中已经大量投资的程序员所面临的许多问题。人们已经对O O P语言有了这样传统的看法:程序员应当抛弃所知道的每件事情并且从一组新概念和新文法重新开始,他应当相信,最好丢掉所有来自过程语言的老行装。从长远角度看,这是对的。但从短期角度看,这些行装还是有价值的。最有价值的可能不是那些已存在的代码库(给出合适的工具,可以转变它),而是已存在的头脑库。作为一个职业 C程序员,如果
13、让他丢掉他知道的关于 C的每一件事,以适应新的语言,那么,几个月内,他将毫无成果,直到他的头脑适应了这一新范例为止。如果他能调整已有的 C知识,并在这个基础上扩展,那么他就可以继续保持高效率,带着已有的知识,进入面向对象程序设计的世界。因为每个人有他自己的程序设计模型,所以这个转变是很混乱的。因此,C+成功的原因是经济上的:转变到O O P需要代价,而转变到C+所花的代价较小。C+的目的是提高效率。效率取决于很多东西,而语言是为了尽可能地帮助使用者,尽可能不用武断的规则或特殊的性能妨碍使用者。C+成功是因为它立足于实际:尽可能地为程序员提供最大便利。1.2.1 较好的C即便程序员在C+环境下继
14、续写C代码,也能直接得到好处,因为C+堵塞了C语言中的一第1章 对象的演化3下载些漏洞,并提供更好的类型检查和编译时的分析。程序员必须先说明函数,使编译器能检查它们的使用情况。预处理器虚拟删除值替换和宏,这就减少了查找疵点的困难。C+有一个性能,称为r e f e r e n c e s(引用),它允许对函数参数和返回值的地址进行更方便的处理。函数重载改进了对名字的处理,使程序员能对不同的函数使用相同的名字。另外,名字空间也加强了名字的控制。许多性能使C的更安全。1.2.2 采用渐进的学习方式与学习新语言有关的问题是效率的问题。所有公司都不可避免地因软件工程师学习新语言而突然降低了效率。C+是
15、对C的扩充,而不是新的文法和新的程序设计模型。程序员学习和理解这些性能,逐渐应用并继续创建有用的代码。这是 C+成功的最重要的原因之一。另外,已有的C代码在C+中仍然是有用的,但因为 C+编译器更严格,所以,重新编译这些代码时,常常会发现隐藏的错误。1.2.3 运行效率有时,以程序执行速度换取程序员的效率是值得的。假如一个金融模型仅在短期内有用,那么快速创建这个模型比所写程序能更快速执行重要。很多应用程序都要求有一定的运行效率,所以C+在更高运行效率时总是犯错。C程序员非常重视运行效率,这让他们认为这个语言不太庞大,也不太慢。产生的代码运行效率不够时,程序员可以用 C+的一些性能做一些调整。C
16、+不仅有与C相同的基本控制能力(和C+程序中直接写汇编语言的能力),非正式的证据指出,面向对象的C+程序的速度与用C写的程序速度相差在1 0%之内,而且常常更接近。用O O P方法设计的程序可能比C的对应版本更有效。1.2.4 系统更容易表达和理解为适合于某问题而设计的类当然能更好地表达这个问题。这意味着写代码时,程序员是在用问题空间的术语描述问题的解(例如“把锁链放在箱子里”),而不是用计算机的术语,也就是解空间的术语,描述问题的解(例如“设置芯片的一位即合上继电器”)。程序员所涉及的是较高层的概念,一行代码能做更多的事情。易于表达所带来的另一个好处是易于维护。据报道,在程序的整个生命周期中
17、,维护占了花费的很大部分。如果程序容易理解,那么它就更容易维护,还能减少创建和维护文档的花费。1.2.5 “库”使你事半功倍创建程序的最快方法是使用已经写好的代码:库。C+的主要目标是让程序员能更容易地使用库,这是通过将库转换为新数据类型(类)来完成的。引入一个库,就是向该语言增加一个新类型。编译器负责这个库如何使用,保证适当的初始化和清除,保证函数被正确地调用,因此程序员的精力可以集中在他想要这个库做什么,而不是如何做上。因为程序的各部分之间名字是隔离的,所以程序员想用多少库就用多少库,不会有像 C语言那样的名字冲突。模板的源代码重用一些重要的类型要求修改源代码以便有效地重用。模板可以自动完
18、成对代码的修改,因而4C+编程思想下载是重用库代码特别有用的工具。用模板设计的类型很容易与其他类型一起工作。因为模板对程序员隐藏了这类代码重用的复杂性,所以特别好用。1.2.6 错误处理在C语言中,错误处理声名狼藉。程序员常常忽视它们,对它们束手无策。如果正在建大而复杂的程序,没有什么比让错误隐藏在某处,且不能指出它来自何处更糟的了。C+的异常处理(见第1 7章的内容)保证能检查到错误并进行处理。1.2.7 大程序设计许多传统语言对程序的规模和复杂性有自身的限制。例如,B A S I C对于某些类型的问题能很快解决,但是如果这个程序有几页纸长,或者超出该语言的正常解题范围,那么它可能永远算不出
19、结果。C语言同样有这样的限制,例如当程序超过 50 000行时,名字冲突就开始成为问题。简言之,程序员用光了函数和变量名。另一个特别糟糕的问题是如果 C语言中存在一些小漏洞错误藏在大程序中,要找出它们是极其困难的。没有清楚的文字告诉程序员,什么时候他的语言会失效,即便有,他也会忽视它们。他不说“我的B A S I C程序太大,我必须用 C重写”,而是试图硬塞进另外几行,增加额外的性能。所以额外的花费就悄悄增加了。设计C+的目的是为了辅助大程序设计,也就是说,去掉小程序和大程序之间复杂性的分界。当程序员写h e l l o-w o r l d类实用程序时,他确实不需要用O O P、模板、名字空间
20、和异常处理,但当他需要的时候,这些性能就有用了。而且,编译器在排除错误方面,对于小程序和大程序一样有效。1.3 方法学介绍所谓方法学是指一组过程和启发式,用以减少程序设计问题的复杂性。在 O O P中,方法学是一个有许多实践的领域。因此,在程序员考虑采用某一方法之前,了解该方法将要解决的问题是很重要的。对于C+,有一点是确实的:它本身就是希望减少程序表达的复杂性。从而不必用更复杂方法学。对于用过程语言的简单方法所不能处理的大型问题,在 C+中用一些简单的方法就足够了。认识到“方法学”一词含义太广是很重要的。实际上,设计和编写程序时,无论做什么都在使用一种方法。只不过因为它是程序员自己的方法而没
21、有意识到。但是,它是程序员编程中的一个过程。如果过程是有效的,只需要用 C+做很小的调整。如果程序员对他的效率和调整程序的方法不满意,他可以考虑采用一种更正式的方法。1.3.1 复杂性为了分析复杂性,先假设:程序设计制定原则来对付复杂性。原则以两种方式出现,每种方式都被单独检查。1)内部原则体现在程序自身的结构中,机灵而有见解的程序员可以通过程序设计语言的表达方式了解这种内部原则。2)外部原则体现在程序的源信息中,一般被描述为“设计文档”(不要与产品文档混淆)。我认为,这两种形式的原则互相不一致:一个是程序的本质,是为了让程序能工作而产生第1章 对象的演化5下载的,另一个是程序的分析,为了将来
22、理解和维护程序而产生的。创建和维护都是程序生命期的基本组成部分。有用的程序设计方法把两者综合为最合适的方式,而不偏向任何一方。1.3.2 内部原则程序设计的演化(C+只是其中的一步)从程序设计模型强加于内部开始,也就是允许程序员为内存位置和机器指令取别名。这是数字机器程序设计的一次飞跃,带动了其他方面的发展,包括从初级机器中抽象出来,向更方便地解决手边问题的模型发展。不是所有这些发展都能流行,起源于学术界并延伸进计算机世界的思想常常依赖于所适应的问题。命名子程序的创建和支持子程序库的连接技术在 5 0年代向前飞跃发展,并且孕育出了两个语言,它们在当时产生了巨大冲击,这就是为科学工作者使用的F
23、O RT R A N(F O R m u l a-T R A N s l a t i o n)和为商业者使用的C O B O L(COmmon Business-Oriented Language)。纯计算机科学中很成功的语言是L i s p(L i s t-P r o c e s s i n g),而面向数学的语言应当是A P L(A ProgrammingL a n g u a g e)。这些语言的共同特点是对过程的使用。L i s p和A P L的创造专注于语言的高雅语言的“m i s s i o n语句”嵌入在处理所有任务情况的引擎中。F O RT R A N和C O B O L的创造
24、是为了解决专门的问题,当这些问题变得更复杂,有新的问题出现时,它们又得到了发展。甚至它们进入衰退期后,仍在发展:F O RT R A N和C O B O L的版本都面向对象进行了扩充(后时髦哲学的基本原则是:任何具有自己独特生活方式的组织,其主要目标就是使这种生活方式永存)。命名子程序在程序设计中起了重要作用,语言的设计围绕着这一原则,特别是A l g o l和P a s c a l。同时另外一些语言也出现了,它们成功地解决了程序设计的一些子集问题,并将它们有序排列。最有趣的两个语言是P r o l o g和F O RT H。前者是围绕着推理机而建立的(在其他语言中常常称作库)。后者是一个可扩
25、充语言,允许程序员重新形成这个语言,以适应所解决的问题,观念上类似于面向对象程序设计。F O RT H还可以改变语言,因而很难维护,并且是内部原则概念最纯正的表达,它强调的是问题一时的解,而不是对这个解的维护。人们还创造了其他许多语言,以解决某一部分的程序设计问题。通常,这些语言以特定的目标开始。例如,B A S I C(Beginners All-purpose Symbolic Instruction Code)是在6 0年代设计的,目的是使程序设计对初学者更简单。A P L的设计是为了数学处理。两种语言都能够解决其他问题,而关键在于它们是否是这些问题集合最理想的解。有一句笑话是,“带着锤
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- C+ 编程 思想 01
限制150内