首页 C++编程思想01

C++编程思想01

举报
开通vip

C++编程思想01 下载 第1章 对象的演化 计算机革命起源于一台机器,程序设计语言也源于一台机器。 然而计算机并不仅仅是一台机器,它是心智放大器和另一种有表述能力的媒体。这一点 使它不很像机器,而更像我们大脑的一部分,更像其他有表述能力的手段,例如写作、绘画、 雕刻、动画制作或电影制作。面向对象的程序设计是计算机向有表述能力的媒体发展中的一 部分。 本章将介绍面向对象程序设计(O O P)的基本概念,然后讨论O O P开发方法,最后介绍使 程序员、项目和公司使用面向对象程序设计方法而采用的策略。 本章是一些背景材料,如果读...

C++编程思想01
下载 第1章 对象的演化 计算机革命起源于一台机器,程序设计语言也源于一台机器。 然而计算机并不仅仅是一台机器,它是心智放大器和另一种有表述能力的媒体。这一点 使它不很像机器,而更像我们大脑的一部分,更像其他有表述能力的手段,例如写作、绘画、 雕刻、动画制作或电影制作。面向对象的程序设计是计算机向有表述能力的媒体发展中的一 部分。 本章将介绍面向对象程序设计(O O P)的基本概念,然后讨论O O P开发方法,最后介绍使 程序员、项目和公司使用面向对象程序设计方法而采用的策略。 本章是一些背景材料,如果读者急于学习这门语言的具体内容,可以跳到第 2章,然后再 回过头来学习本章。 1.1 基本概念 C + +包含了比面向对象程序设计基本概念更多的内容,读者应当在学习设计和开发程序之 前先理解该语言所包含的基本概念。 1.1.1 对象:特性+行为[1] 第一个面向对象的程序设计语言是 6 0年代开发的S i m u l a - 6 7。其目的是为了解决模拟问 快递公司问题件快递公司问题件货款处理关于圆的周长面积重点题型关于解方程组的题及答案关于南海问题 。 典型的模拟问题是银行出纳业务,包括出纳部门、顾客、业务、货币的单位等大量的“对象”。 把那些在程序执行期间除了状态之外其他方面都一样的对象归在一起,构成对象的“类”,这 就是“类”一词的来源。 类描述了一组有相同特性(数据元素)和相同行为( 函数 excel方差函数excelsd函数已知函数     2 f x m x mx m      2 1 4 2拉格朗日函数pdf函数公式下载 )的对象。类实际上就是数据类 型,例如,浮点数也有一组特性和行为。区别在于程序员定义类是为了与具体问题相适应,而 不是被迫使用已存在的数据类型。这些已存在的数据类型的设计动机仅仅是为了描述机器的存 储单元。程序员可以通过增添他所需要的新数据类型来扩展这个程序设计语言。该程序设计系 统欢迎创建、关注新的类,对它们进行与内部类型一样的类型检查。 这种方法并不限于去模拟具体问题。尽管不是所有的人都同意,但大部分人相信,任何程 序都模拟所设计系统。O O P技术能很容易地将大量问题归纳成为一个简单的解,这一发现产生 了大量的O O P语言,其中最著名的是S m a l l t a l k—C++ 之前最成功的O O P语言。 抽象数据类型的创建是面向对象程序设计中的一个基本概念。抽象数据类型几乎能像内部类 型一样准确工作。程序员可以创建类型的变量(在面向对象程序设计中称为“对象”或“实例”) 并操纵这些变量(称为发送“消息”或“请求”,对象根据发来的消息知道需要做什么事情)。 1.1.2 继承:类型关系 类型不仅仅说明一组对象上的约束,还说明与其他类型之间的关系。两个类型可以有共同 的特性和行为,但是,一个类型可能包括比另一个类型更多的特性,也可以处理更多的消息 [1] 这一描述部分引自我对《The Tao of Objects》(Gary Entsminger著)一书的介绍。 (或对消息进行不同的处理)。继承表示了基本类型和派生类型之间的相似性。一个基本类型具 有所有由它派生出来的类型所共有的特性和行为。程序员创建一个基本类型以描述系统中一些 对象的思想核心。由这个基本类型派生出其他类型,表达了认识该核心的不同途径。 例如,垃圾再生机要对垃圾进行分类。这里基本类型是“垃圾”, 每件垃圾有重量、价值 等等,并且可以被破碎、融化或分解。这样,可以派生出更特殊的垃圾类型,它们可以有另外 的特性(瓶子有颜色)或行为(铝可以被压碎,钢可以被磁化)。另外,有些行为可以不同 (纸的价值取决于它的种类和状态)。程序员可以用继承建立类的层次结构,在该层次结构中用 类型术语来表述他需要解决的问题。 第二个例子是经典的形体问题,可以用于计算机辅助设计系统或游戏模拟中。这里基本类 型是“形体”,每个形体有大小、颜色、位置等。每个形体能被绘制、擦除、移动、着色等。 由此,可以派生出特殊类型的形体:圆、正方形、三角形等,它们中的每一个都有另外的特性 和行为,例如,某些形体可以翻转。有些行为可以不同(计算形体的面积)。类型层次结构既 体现了形体间的类似,又体现了它们之间的区别。 用与问题相同的术语描述问题的解是非常有益的,这样,从问题描述到解的描述之间就不 需要很多中间模型(程序语言解决大型问题,就需要中间模型)。面向对象之前的语言,描述 问题的解不可避免地要用计算机术语。使用对象术语,类型层次结构是主要模型,所以可以从 现实世界中的系统描述直接进入代码中的系统描述。实际上,使用面向对象设计,人们的困难 之一是从开始到结束过于简单。一个已经习惯于寻找复杂解的、训练有素的头脑,往往会被问 题的简单性难住。 1.1.3 多态性 当处理类型层次结构时,程序员常常希望不把对象看作是某一特殊类型的成员,而把它看 作基本类型成员,这样就可以编写不依赖于特殊类型的代码。在形体例子中,函数可以对一般 形体进行操作,而不关心它们是圆、正方形还是三角形。所有的形体都能被绘制、擦除和移动, 所以这些函数能简单地发送消息给一个形体对象,而不考虑这个对象如何处理这个消息。 这样,新添类型不影响原来的代码,这是扩展面向对象程序以处理新情况的最普通的方法。 例如,可以派生出形体的一个新的子类,称为五边形,而不必修改那些处理一般形体的函数。 通过派生新子类,很容易扩展程序,这个能力很重要,因为它极大地减少了软件维护的花费。 (所谓“软件危机”正是由软件的实际花费远远超出人们的想象而产生的。) 如果试图把派生类型的对象看作它们的基本类型(圆看作形体,自行车看作车辆,鸬鹚看作 鸟),就有一个问题:如果一个函数告诉一个一般形体去绘制它自己,或者告诉一个一般的车辆去 行驶,或者告诉一只一般的鸟去飞,则编译器在编译时就不能确切地知道应当执行哪段代码。同 样的问题是,消息发送时,程序员并不想知道将执行哪段代码。绘图函数能等同地应用于圆、正 方形或三角形,对象根据它的特殊类型来执行合适的代码。如果增加一个新的子类,不用修改函 数调用,就可以执行不同的代码。编译器不能确切地知道执行哪段代码,那么它应该怎么办呢? 在面向对象的程序设计中,答案是巧妙的。编译器并不做传统意义上的函数调用。由非 O O P编译器产生的函数调用会引起与被调用代码的“早捆绑”,对于这一术语,读者可能还没 有听说过,因为从来没有想到过它。早捆绑意味着编译器对特定的函数名产生调用,而连接器 确定调用执行代码的绝对地址。对于 O O P,在程序运行之前,编译器不确定执行代码的地址, 所以,当消息发送给一般对象时,需要采用其他的 方案 气瓶 现场处置方案 .pdf气瓶 现场处置方案 .doc见习基地管理方案.doc关于群访事件的化解方案建筑工地扬尘治理专项方案下载 。 为了解决这一问题,面向对象语言采用“晚捆绑”的思想。当给对象发送消息时,在程序 2 C + +编程思想 下载 运行之前不去确定被调用的代码。编译器保证这个被调用的函数存在,并完成参数和返回值的 类型检查,但是它不知道将执行的准确代码。 为了实现晚捆绑,编译器在真正调用的地方插入一段特殊的二进制代码。通过使用存放在 对象自身中的信息,这段代码在运行时计算被调用函数的地址(这一问题将在第 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 语言编写的过程程序就是一些数据定义和函数调用。要理解这种程序 的含义,程序员必须掌握函数调用和函数实现的本身。这就是过程程序需要中间表示的原因。 中间表示容易引起混淆,因为中间表示的表述是原始的,更偏向于计算机,而不偏向于所解决 的问题。 因为 C++ 向 C 语言增加了许多新概念,所以程序员很自然地认为, C + +程序中的m a i n ( )会 比功能相同的 C 程序更复杂。但令人吃惊的是,一个写得很好的 C + +程序一般要比功能相同的 C程序更简单和容易理解。程序员只会看到一些描述问题空间对象的定义(而不是计算机的描 述),发送给这些对象的消息。这些消息表示了在这个空间的活动。面向对象程序设计的优点 之一是通过阅读,很容易理解代码。通常,面向对象程序需要较少的代码,因为问题中的许多 部分都可以用已存在的库代码。 1.2 为什么C++会成功 C + +能够如此成功,部分原因是它的目标不只是为了将 C语言转变成O O P语言(虽然这是 最初的目的),而且还为了解决当今程序员,特别是那些在 C语言中已经大量投资的程序员所 面临的许多问题。人们已经对O O P语言有了这样传统的看法:程序员应当抛弃所知道的每件事 情并且从一组新概念和新文法重新开始,他应当相信,最好丢掉所有来自过程语言的老行装。 从长远角度看,这是对的。但从短期角度看,这些行装还是有价值的。最有价值的可能不是那 些已存在的代码库(给出合适的工具,可以转变它),而是已存在的头脑库。作为一个职业 C 程序员,如果让他丢掉他知道的关于 C的每一件事,以适应新的语言,那么,几个月内,他将 毫无成果,直到他的头脑适应了这一新范例为止。如果他能调整已有的 C知识,并在这个基础 上扩展,那么他就可以继续保持高效率,带着已有的知识,进入面向对象程序设计的世界。因 为每个人有他自己的程序设计模型,所以这个转变是很混乱的。因此, C + +成功的原因是经济 上的:转变到O O P需要代价,而转变到C + +所花的代价较小。 C + +的目的是提高效率。效率取决于很多东西,而语言是为了尽可能地帮助使用者,尽可 能不用武断的规则或特殊的性能妨碍使用者。 C + +成功是因为它立足于实际:尽可能地为程序 员提供最大便利。 1.2.1 较好的C 即便程序员在C + +环境下继续写C代码,也能直接得到好处,因为C + +堵塞了C语言中的一 第1章 对象的演化 3 下载 quixote 线条 quixote 线条 quixote 线条 些漏洞,并提供更好的类型检查和编译时的分析。程序员必须先说明函数,使编译器能检查它 们的使用情况。预处理器虚拟删除值替换和宏,这就减少了查找疵点的困难。C + +有一个性能, 称为r e f e r e n c e s (引用),它允许对函数参数和返回值的地址进行更方便的处理。函数重载改进了 对名字的处理,使程序员能对不同的函数使用相同的名字。另外,名字空间也加强了名字的控 制。许多性能使C的更安全。 1.2.2 采用渐进的学习方式 与学习新语言有关的问题是效率的问题。所有公司都不可避免地因软件工程师学习新语言 而突然降低了效率。 C + +是对C的扩充,而不是新的文法和新的程序设计模型。程序员学习和 理解这些性能,逐渐应用并继续创建有用的代码。这是 C + +成功的最重要的原因之一。 另外,已有的C代码在C + +中仍然是有用的,但因为 C + +编译器更严格,所以,重新编译 这些代码时,常常会发现隐藏的错误。 1.2.3 运行效率 有时,以程序执行速度换取程序员的效率是值得的。假如一个金融模型仅在短期内有用, 那么快速创建这个模型比所写程序能更快速执行重要。很多应用程序都要求有一定的运行效率, 所以C + +在更高运行效率时总是犯错。 C程序员非常重视运行效率,这让他们认为这个语言不 太庞大,也不太慢。产生的代码运行效率不够时,程序员可以用 C + +的一些性能做一些调整。 C + +不仅有与C相同的基本控制能力(和C + +程序中直接写汇编语言的能力),非正式的证 据指出,面向对象的C + +程序的速度与用C写的程序速度相差在±1 0 %之内,而且常常更接近。 用O O P方法设计的程序可能比C的对应版本更有效。 1.2.4 系统更容易表达和理解 为适合于某问题而设计的类当然能更好地表达这个问题。这意味着写代码时,程序员是在 用问题空间的术语描述问题的解(例如“把锁链放在箱子里”),而不是用计算机的术语,也就 是解空间的术语,描述问题的解(例如“设置芯片的一位即合上继电器”)。程序员所涉及的是 较高层的概念,一行代码能做更多的事情。 易于表达所带来的另一个好处是易于维护。据报道,在程序的整个生命周期中,维护占了 花费的很大部分。如果程序容易理解,那么它就更容易维护,还能减少创建和维护文档的花 费。 1.2.5 “库”使你事半功倍 创建程序的最快方法是使用已经写好的代码:库。 C + +的主要目标是让程序员能更容易地 使用库,这是通过将库转换为新数据类型(类)来完成的。引入一个库,就是向该语言增加一 个新类型。编译器负责这个库如何使用,保证适当的初始化和清除,保证函数被正确地调用, 因此程序员的精力可以集中在他想要这个库做什么,而不是如何做上。 因为程序的各部分之间名字是隔离的,所以程序员想用多少库就用多少库,不会有像 C语 言那样的名字冲突。 • 模板的源代码重用 一些重要的类型要求修改源代码以便有效地重用。模板可以自动完成对代码的修改,因而 4 C + +编程思想 下载 是重用库代码特别有用的工具。用模板设计的类型很容易与其他类型一起工作。因为模板对程 序员隐藏了这类代码重用的复杂性,所以特别好用。 1.2.6 错误处理 在C语言中,错误处理声名狼藉。程序员常常忽视它们,对它们束手无策。如果正在建大 而复杂的程序,没有什么比让错误隐藏在某处,且不能指出它来自何处更糟的了。 C + +的异常 处理(见第1 7章的内容)保证能检查到错误并进行处理。 1.2.7 大程序设计 许多传统语言对程序的规模和复杂性有自身的限制。例如, B A S I C对于某些类型的问题能 很快解决,但是如果这个程序有几页纸长,或者超出该语言的正常解题范围,那么它可能永远 算不出结果。C语言同样有这样的限制,例如当程序超过 50 000行时,名字冲突就开始成为问 题。简言之,程序员用光了函数和变量名。另一个特别糟糕的问题是如果 C语言中存在一些小 漏洞—错误藏在大程序中,要找出它们是极其困难的。 没有清楚的文字告诉程序员,什么时候他的语言会失效,即便有,他也会忽视它们。他不 说“我的B A S I C程序太大,我必须用 C重写”,而是试图硬塞进另外几行,增加额外的性能。 所以额外的花费就悄悄增加了。 设计C + +的目的是为了辅助大程序设计,也就是说,去掉小程序和大程序之间复杂性的分 界。当程序员写h e l l o - w o r l d类实用程序时,他确实不需要用O O P、模板、名字空间和异常处理, 但当他需要的时候,这些性能就有用了。而且,编译器在排除错误方面,对于小程序和大程序 一样有效。 1.3 方法学介绍 所谓方法学是指一组过程和启发式,用以减少程序设计问题的复杂性。在 O O P中,方法学 是一个有许多实践的领域。因此,在程序员考虑采用某一方法之前,了解该方法将要解决的问 题是很重要的。对于C + +,有一点是确实的:它本身就是希望减少程序表达的复杂性。从而不 必用更复杂方法学。对于用过程语言的简单方法所不能处理的大型问题,在 C + +中用一些简单 的方法就足够了。 认识到“方法学”一词含义太广是很重要的。实际上,设计和编写程序时,无论做什么都 在使用一种方法。只不过因为它是程序员自己的方法而没有意识到。但是,它是程序员编程中 的一个过程。如果过程是有效的,只需要用 C + +做很小的调整。如果程序员对他的效率和调整 程序的方法不满意,他可以考虑采用一种更正式的方法。 1.3.1 复杂性 为了分析复杂性,先假设:程序设计制定原则来对付复杂性。 原则以两种方式出现,每种方式都被单独检查。 1) 内部原则体现在程序自身的结构中,机灵而有见解的程序员可以通过程序设计语言的表 达方式了解这种内部原则。 2) 外部原则体现在程序的源信息中,一般被描述为“设计文档”(不要与产品文档混淆)。 我认为,这两种形式的原则互相不一致:一个是程序的本质,是为了让程序能工作而产生 第1章 对象的演化 5 下载 quixote 线条 quixote 线条 的,另一个是程序的分析,为了将来理解和维护程序而产生的。创建和维护都是程序生命期的 基本组成部分。有用的程序设计方法把两者综合为最合适的方式,而不偏向任何一方。 1.3.2 内部原则 程序设计的演化(C + +只是其中的一步)从程序设计模型强加于内部开始,也就是允许程 序员为内存位置和机器指令取别名。这是数字机器程序设计的一次飞跃,带动了其他方面的发 展,包括从初级机器中抽象出来,向更方便地解决手边问题的模型发展。不是所有这些发展都 能流行,起源于学术界并延伸进计算机世界的思想常常依赖于所适应的问题。 命名子程序的创建和支持子程序库的连接技术在 5 0年代向前飞跃发展,并且孕育出了两个 语言,它们在当时产生了巨大冲击,这就是为科学工作者使用的 F 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 Programming L 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的创造是为了解决专 门的问题,当这些问题变得更复杂,有新的问题出现时,它们又得到了发展。甚至它们进入衰 退期后,仍在发展: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。前者是围绕着推理机而建立的(在其他语言 中常常称作库)。后者是一个可扩充语言,允许程序员重新形成这个语言,以适应所解决的问 题,观念上类似于面向对象程序设计。 F O RT H还可以改变语言,因而很难维护,并且是内部 原则概念最纯正的表达,它强调的是问题一时的解,而不是对这个解的维护。 人们还创造了其他许多语言,以解决某一部分的程序设计问题。通常,这些语言以特定的 目标开始。例如,B A S I C(Beginners All-purpose Symbolic Instruction Code)是在6 0年代设计 的,目的是使程序设计对初学者更简单。 A P L的设计是为了数学处理。两种语言都能够解决其 他问题,而关键在于它们是否是这些问题集合最理想的解。有一句笑话是,“带着锤子三年, 看什么都是钉子”。这反映了根本的经济学真理:如果我们只有 B A S I C或A P L语言,特别是, 当最终期限很短且这个解的生命期有限时,它就是我们问题最好的解。 然而,最终考虑两个因素:复杂性的管理和维护(将在下一部分讨论)。即这种语言首先 是为某一领域开发的,而程序员又不愿花很长时间来熟悉这门语言,其结果只能使程序越来越 长,使手头的问题屈服于语言。界限是模糊的:谁能说什么时候您的语言会使您失望呢?这不 是马上就出现的。 问题的解开始变长,并且对于程序员更具挑战性。为了知道语言大概的限制,你得更聪明, 这种聪明变成了一种 标准 excel标准偏差excel标准偏差函数exl标准差函数国标检验抽样标准表免费下载红头文件格式标准下载 ,也就是“为了使该语言工作而努力”。这似乎是人类的操作方式, 而不是遇到缺陷就抱怨,并且不再称它为缺陷。 最终,程序设计问题对于求解和维护变得太困难了,即求得的解太昂贵了。人们最终明白 了,程序的复杂性超出了我们能够处理的程度。尽管一大类程序设计要求开发期间去做大部分 工作并创建要求最小维护的解(或者简单地丢掉这个解,或者用不同的解替换它),但这只是 问题的一部分。一般情况是,我们把软件看作是为人们提供服务的工具。如果用户的需要变化 6 C + +编程思想 下载 了,服务就必须随着变化。这样,当第一版本开始运行时,项目并没有结束。项目是一个不断 进化的生命体。程序的更新变成了一般程序设计问题的一个部分。 1.3.3 外部原则 为了更新和改善程序,需要更新思考问题的方法。它不只是“我们如何让程序工作”,而 是“我们如何让程序工作并且使它容易改变”。这里就有一个新问题:当我们只是试图让程序 工作时,我们可以假设开发组是稳定的(总之,我们可以希望这样),但是,如果我们正在考 虑程序的整个生命期,就必须假设开发组成员会改变。这意味着,新组员必须以某种方式学习 原程序的要点,并与老组员互相通讯(也许通过对话)。这样,该程序就需要某种形式的设计 文档。 因为只想让程序工作,文档并不是必需的,所以还没有像由程序设计语言强加于程序那样 的、强加于创建文档的规则。这样,如果要求文档满足特定的需要,就必须对文档强加外部原 则。文档是否“工作”,这很难确定(并且需要在程序一生中验证),因此,对外部原则“最好” 形式的争论.比对“最好”程序设计语言的争论更激烈。 决定外部原则时,头脑中的重要问题是“我准备解决什么问题”。问题的根本就是上面所 说的“我们如何让它工作和使它容易改变”。然而,这个问题常常有多种解释:它变成了“我 如何才能与F o o b l e B l a h文档规范说明一致,以使政府会为此给我拨款”。这样,外部原则的目 的是为了建立文档,而不是为了设计好的、可维护的程序。文档竟然变得比程序本身更重要 了。 被问到未来一般和特殊的计算的方向时,我会从这样的问题开始:哪种解花费较少?假设 这个解满足需要,价格的不同足以使程序员放弃他当前做事情的习惯方式吗?如果他的方法包 括存储在项目分析和设计过程中所创建的每个文档,并且包括当项目进化时维护这些文档,那 么当项目更新时,他的系统将花费很大,但是它能使新组员容易理解(假设没有那么多的使人 害怕阅读的文档)。这样创建和维护方法的花费会和它打算替代方法的花费一样多。 外部结构系列的另一个极端是最小化方法。为完成设计而进行足够的分析,然后丢掉它们, 使得程序员不再花时间和钱去维护它;为开始编码而做足够的设计,然后丢掉这个设计,使得 程序员不再花时间和钱去维护这些文档;然后使得代码是一流的和清晰的,代码中只需要最少 的注释。为了使新组员快速参与项目,代码连同注释就足够了。因为在所有这些乏味的文档上, 新组员只需花费很少的时间(总之,没有人真地理解它们),所以他能较快地参与工作。 即便不维护文档,丢掉文档也不是最好的办法,因为这毕竟是程序员所做的有效工作。某 些形式的文档通常是必须的(参看本章后面的描述)。 1. 通讯 对于较大的项目,期望代码像文档一样充分是不合理的,尽管我们在实际中常常这样期望。 但是,代码包含了我们实际上希望外部原则所产生的事物的本质:通讯。我们只是希望能与改 进这个程序的新组员通讯就足够了。但是,我们还想使花费在外部原则上的钱最少,因为最终 人们只为这个程序所提供的服务付钱,而不是为它后面的设计文档付钱。为了真正有用,外部 原则应当做比只产生文档更多的事情—它应当是项目组成员在创建设计时为了讨论问题而采 用的通讯方法。理想的外部原则目标是使关于程序分析和设计的通讯更容易。这对于现在为这 个程序而工作的人们和将来为这个程序而工作的人们是有帮助的。中心问题不只是为了能通讯, 而为了产生好的设计。 人们(特别是程序员)被计算机吸引(由于机器为他们做工作),出于经济原因,要求开 第1章 对象的演化 7 下载 发者为机器做大量工作的外部原则似乎从一开始就注定要失败。成功的方法(也就是人们习惯 的方法)有两个重要的特征: 1) 它帮助人们进行分析和设计。这就是,用这种方法比用别的方法对分析和设计中的思考 和通讯要容易得多。目前的效率和采用这种方法后的效率应当明显不同。否则,人们可能还留 在原地。还有,它的使用必须足够简单,不需用手册。当程序员正在解决问题时,要考虑简单 性,而不管他适用于符号还是技术。 2) 没有短期回报,就不会加强投资。在通向目标的可见的进展中,没有短期回报,人们就 不会感到采用一种方法能使效率提高,就会回避它。不能把这个进展误认为是从一种中间形式 到另一种中间形式的变换。程序员可以看到他的类,连同类之间互相发送的消息一起出现。为 某人创造一种方法,就像武断的约束,因为它是简单的心理状态:人们希望感到他们正在做创 造性的工作,如果某种方法妨碍他们而不是帮助他们飞快地接近目标,他们将设法绕过这种方 法。 2. 量级 在方法学上反对我的观点之一是:“好了,您能够侥幸成功是因为您正在做的小项目很短。” 听众对“小”的理解因人而异。虽然这种看法并不全对,但它包含一个正确的核心:我们所需 要的原则与我们正在努力解决问题的量级有关。小项目完全不需要外部原则,这不同于个别程 序员正在解的生命期问题的模式。涉及很多人的大项目会使人们之间有一些通讯,所以必须使 通讯具有形式化方法,以使通讯有效和准确。 麻烦的是介于它们之间的项目。它们对外部原则的需要程度可能在很大程度上依赖于项目 的复杂性和开发者的 经验 班主任工作经验交流宣传工作经验交流材料优秀班主任经验交流小学课改经验典型材料房地产总经理管理经验 。确实,所有中等规模的项目都不需要忠实于成熟的方法,即产生许 多报告和很多文档。一些项目也许这样做,但许多项目可以侥幸成功于“方法学简化”(代码 多而文档少)。我们面前的所有方法学的复杂性可以减少到 8 0 %~2 0 %的(或更少的)规则。 我们正在被方法学的细节淹没,在所解决的程序设计问题中,可能只有不足 2 0 %的问题需要这 些方法学。如果我们的设计是充分的,并且维护也不可怕,那么我们也许不需要方法学或不全 部需要它。 3. OOP是结构化的吗 现在提出一个更有意义的问题。为了使通讯方便,假设方法学是需要的。这种关于程序的 元通讯是必须的,因为程序设计语言是不充分的—它太原始,趋向于机器范例,对于谈论问 题不很有用。例如,过程程序设计方法要求用数据和变换数据的函数作为术语谈论程序。因为 这不是我们讨论实际问题的方法,所以必须在问题描述和解描述之间翻译来翻译去。一旦得到 了一个解描述并且实现了它,以后无论何时对这个解描述做改变就要对问题描述做改变。这意 味着必须从机器模式返回问题空间。为了得到真正可维护的程序,并且能够适应问题空间上的 改变,这种翻译是必须的。投资和组织的需要似乎要求某种外部原则。过程程序的最重要的方 法学是结构化技术。 现在考虑,是否解空间上的语言可以完全脱离机器模式?是否可以强迫解空间使用与问题 空间相同的术语? 例如,在气候控制大楼中的空气调节器就变成了气候调节程序的空气调节器,自动调温器 变成了自动调温程序,等等。(这是按直觉做的,与O O P不一致)。突然,从问题空间到解空间 的翻译变成了次要问题。可以想象,在程序分析、设计和实现的每一阶段,能使用相同的术语 学、相同的描述,这样,这个问题就变成了“如果文档(程序)能够充分地描述它自身,我们 仍然需要关于这个文档的文档吗?”如果 O O P做它所主张的事情,程序设计的形式就变成了这 8 C + +编程思想 下载 样:在结构化技术中所遇到的困难在新领域中可能不复存在了。 这个论点也为一个思想实验所揭示。假设程序员需要写一些小实用程序,例如能在文本文 件上完成一个操作的程序(就像在第6章的后几页上可找到的那样),它们要程序员花费几分钟, 最困难的要花费几小时去写。现在假设回到5 0年代,这个项目必须用机器语言或汇编语言来写, 使用最少的库函数,它需要许多人几星期或几个月的时间。在 5 0年代需要大量的外部原则和管 理,现在不需要了。显然,工具的发展已经极大地增加了我们不用外部原则解决问题的复杂性 (同样很显然,我们将发现的问题也更加复杂)。 这并不是说可以不需要外部原则,有用的 O O P外部原则解决的问题与有用的过程程序设计 外部原则所解决的问题不同,特别是, O O P方法的目标首先必须是产生好的设计。好设计不仅 要促进重用,而且它与项目的各级开发者的需要是一致的。这样,开发者就会更喜欢采用这样 的系统。让我们基于这些观点考虑O O P设计方法中的一些问题。 1.3.4 对象设计的五个阶段 对象的设计不限于写程序的时期,它出现在一系列阶段。有这种观点很有好处,因为我们 不再期望设计立刻尽善尽美,而是认识到,对对象做什么和它应当像什么的理解是随着时间的 推移而产生的。这个观点也适用于不同类型程序的设计。特殊类型程序的模式是通过一次又一 次地求解问题而形成的 [ 1 ]。同样,对象有自己的模式,通过理解、使用和重用而形成。 下面是描述,不是方法。它简直就是对象期望的设计出现时的观察结果。 1) 对象发现 这个阶段出现在程序的最初分析期间。可以通过寻找外部因素与界线、系统 中的元素副本和最小概念单元而发现对象。如果已经有了一组类库,某些对象是很明显的。类 之间的共同性(暗示了基类和继承类),可以立刻出现或在设计过程的后期出现。 2) 对象装配 我们在建立对象时会发现需要一些新成员,这些新成员在对象发现时期未出 现过。对象的这种内部需要可能要用新类去支持它。 3) 系统构造 对对象的更多要求可能出现在以后阶段。随着不断的学习,我们会改进我们 的对象。与系统中其它对象通讯和互相连接的需要,可能改变已有的类或要求新类。 4) 系统扩充 当我们向系统增添新的性能时,可能发现我们先前的设计不容易支持系统扩 充。这时,我们可以重新构造部分系统,并很可能要增加新类。 5) 对象重用 这是对类的真正的重点测试。如果某些人试图在全新的情况下重用它,他们 会发现一些缺点。当我们修改一个类以适应更新的程序时,类的一般原则将变得更清楚,直到 我们有了一个真正可重用的对象。 对象开发原则 在这些阶段中,提出考虑开发类时所需要的一些原则: 1) 让特殊问题生成一个类,然后在解其他问题时让这个类生长和成熟。 2) 记住,发现所需要的类,是设计系统的主要内容。如果已经有了那些类,这个项目就不 困难了。 3) 不要强迫自己在一开始就知道每一件事情,应当不断地学习。 4) 开始编程,让一部分能够运行,这样就可以证明或反驳已生成的设计。不要害怕过程语 言风格的细面条式的代码—类分割可以控制它们。坏的类不会破坏好的类。 5) 尽量保持简单。具有明显用途的不太清楚的对象比很复杂的接口好。我们总能够从小的 第1章 对象的演化 9 下载 [1] 参看Design Patterns:Elements of Reusable Object-Oriented Software by Erich Gamma et al., Addison-We s l e y, 1995。 和简单的类开始,当我们对它有了较好地理解时再扩展这个类接口,但不可能简化已存在的类 接口。 1.3.5 方法承诺什么 由于不同的原因,方法承诺的东西往往比它们能够提供的东西多得多。这是不幸的,因为 当策略和不实际的期望同时出现时程序员会疑神疑鬼。一些方法的坏名声,使得程序员丢弃了 手上的其他方法,忽视了一些有价值的技术。 1. 管理者的银子弹 最坏的许诺是“这个方法将解决您的所有问题”。这一许诺也很可能用这样的思想表达, 即一个方法将解决实际上不存在解的问题,或者至少在程序的设计领域内没有解的问题:一个 贫穷的社团文化,疲惫的、互相疏远或敌对的项目组成员;不充分的时间和资源;或试图解决 一个实际上不能解的问题(资源不足)。最好的方法学,不管它许诺什么,都不解决这些或类 似的任何问题。无论O O P还是C + +,都无助于这样的问题。不幸的是,在这种情况下管理员是 这样的人:对于银子弹的警报 [ 1 ],他是最易动摇的。 2. 提高效率的工具 这就是方法应当成为的东西。提高生产效率不仅取决于管理容易和花费不大,而且取决于 一开始就创建好的设计。由于一些方法学的创造动机是为了改善维护,所以它们就片面地强调 维护问题,而忽视了设计的漂亮和完整。实际上,好的设计应当是首要的目标,好的 O O P设计 也应当容易维护,但这是它的附加作用。 1.3.6 方法应当提供什么 不管为特殊方法提出什么要求,它都应当提供这一节所列出的基本功能:允许为讨论这个 项目将完成什么和如何做而进行通讯的约定;支持项目结构化的系统;能用某抽象形式描述项 目的一组工具(使得程序员能容易地观察和操作项目)。如过去介绍过的,一个更微妙的问题 是该方法对待最宝贵资源—组员积极性的“态度”。 1. 通讯约定 对于很小的项目组,可以用紧密接触的方式自然维持通讯。这是理想的请况。 C + +的最大 的好处之一是它可以使项目由很少的项目组成员建立,因此,明白表示的通讯能使维护变得容 易,因而通讯费用低,项目组能更快地建立。 情况并不总是这样理想,有可能项目组成员很多,项目很复杂,这就需要某种形式的通 讯原则。方法提供一种在项目组成员之间形成“约定”的办法。可以用两种方式看待这样的 约定: 1) 敌对的 约定基于参与的当事人之间互有疑问,以使得没有人出格且每个人都做应该做 的事情。约定清楚地说明,如果他们不做这些事,会出现坏的结果。这样看待任何约定,我们 就已经输了,因为我们已经认为其他人是不可信赖的了。如果不能信任某人,约定并不能确保 好的行为。 2) 信息的 约定是一种努力,使每个人都知道我们已经在哪些方面取得了一致的意见。这 是对通讯的辅助,使得每个人能看到它并说,“是的,这是我认为我们将要做的事情”。它是协 议作出后对协议的表述,只是消除误解。这类约定能最小化,并容易读。 10 C + +编程思想 下载 [1] A reference to vampires made in The Mythical Man-Month, by Fred Brooks, Addision-We s l e y, 1975。 有用的方法不鼓励敌对的约定,而重点是在通讯上。 2. 使系统结构化 结构化是系统的核心。如果一个方法能做些事情,那么它就必须能够告诉程序员: 1) 需要什么类 2) 如何把它们连接在一起,形成一个工作系统。 一个方法产生这些回答需要一个过程,即首先对问题进行分析,最终对类、系统和类之间 传递的消息进行某种表述。 3. 描述工具 模型不应当比它描述的系统更复杂。一种好的模型仅提供一种抽象。 程序员一定不会使用只对特殊方法有用的描述工具。他能使自己的工具适合自己的各种需 要。(例如在本章后面,建议一种符号,用于商业字处理机。)下面是有用的符号原则: 1) 方法中不含有不需要的东西。记住,“七加减二”规则的复杂性。(瞬间,人们只能在头 脑中存放这么多的条目。)额外的细节就变成了负担,必须维护它,为它花钱。 2) 通过深入到描述层,人们应当能够得到所需要的信息。即我们可以在较高的抽象层上创 建一些隐藏的层,仅在需要时,它们才可见。 3) 符号应当尽可能少。“过多的噱头使得软件变坏” 。 4) 系统设计和类设计是互相隔离的问题。类是可重用工具,而系统是对特殊问题的解(虽 然系统设计也是可重用的)。符号应当首先集中在系统设计方面。 5) 类设计符号是必须的吗?由C + +语言提供的类表达对大多数情况是足够的。如果符号在 描述类方面不能比用O O P语言描述有一个明显的推进,那么就不要用它。 6) 符号应当在隐藏对象的内部实现。在设计期间,这些内部实现一般不重要。 7) 保持符号简单。我们想用我们的方法做的所有事情基本上就是发现对象及其如何互相连 接以形成系统。如果一个方法或符号要求更多的东西,则应当问一问,该方法花费我们的时间 是否合理。 4. 不要耗尽最重要的资源 我的朋友Michael Wi l k来自学术界,也许并不具备做评判的资格(从某个人那里听说的新 观点),但他观察到,项目、开发组或公司拥有的最重要的资源是积极性。不管问题如何困难, 过去失败多么严重,工具多么原始或不成套,积极性都能克服这些障碍。 不幸的是,各种管理技术常常完全不考虑积极性,或因为不容易度量它,就认为它是“不 重要”的因素,他们认为,如果管理完善,项目就能强制完成。这种认识有压制开发组积极性 的作用,因为他们会感到公司除了利益动机以外就没有感兴趣的东西了。一旦发生这种现象, 组员就变成了“雇员”,看着钟,想着感兴趣的、分心的事情。 方法和管理技术是建立在动机和积极性的基础上的,最宝贵的资源应当是对项目真正感兴 趣。至少,应当考虑O O P设计方法对开发组士气起的作用。 5. “必”读 在选择任何方法之前,从并不想出售方法的人那儿得到意见是有帮助的。不真正地理解我 们想要一种方法是为了做什么或它能为我们做什么,那么采用一种方法很容易。其他人正在用 它,这似乎是很充足的理由。但是,人们有一种奇怪的心理:如果他们相信某件事能解决他们 的问题,他们就将试用它(这是经验,是好的)。但是,如果它不能解决他们的问题,他们可 能加倍地努力,并且开始大声宣布他们已经发现了伟大的东西(这是否定,是不好的)。这个 假设是,如果见到同一条船上有其他人,就不感到孤单,即便这条船哪儿也不去。 第1章 对象的演化 11 下载 这并不是说所有的方法学都什么也不做,而是用精神方法使程序员武装到牙齿,这些方法 能使程序员保持实验精神(“它不工作,让我们再试其它方法”)和跳出否定方式(“不,这根 本不是问题,每样东西都很好,我们不需要改变”)。我认为,在选择方法之前读下面的书,会 为我们提供这些精神武器。 《软件的创造力》(Software Creativity,Robert Glass编,P r e n t i c e - H a l l , 1 9 9 5)。这是我所看 到的讨论整个方法学前景最好的书。它是由 G l a s s已经写过的短文和文章以及收集到的东西组 成的(P. J . P l a u g e r是一个撰稿者),反映出他在该主题上多年的思考和研究。他们愉快地说明什 么是必须的,并不东拉西扯和扫我们的兴,不说空话,而且,这里有几百篇参考文献。所有的 程序员和管理者在陷入方法学泥潭之前应当读这本书 [ 1 ]。 《人件》(Pe o p l e w a r e,Tom Demarco 和Timothy Lister 编,Dorset House,1987)。虽然他们 有软件开发方面的背景,而且本书大体上是针对项目和开发组的,但是这本书的重点是人和他 们的需要方面,而不是技术和技术的需要方面。他们谈论创造一个环境,在其中人们是幸福和 高效率的,而不是决定人们应当遵守什么样的规则,以使得他们成为机器的合适部件。我认为, 这本书后面的观点是对程序员在采用X Y Z方法,然后平静地做他们总是做的事情时微笑和点头 的最大贡献。 《复杂性》(C o m p l e x i t y, M. Mitchell Wa l d r o p编,Simon & Schuster, 1992)。此书集中了 Santa Fe, New Mexico的一组持不同观点的科学家,讨论单个原则不能解决的实际问题(经济 学中的股票市场、生物学的生命原始形式、为什么人们做他们在社会中应做的事情,等等)。 通过物理学、经济学、化学、数学、计算机科学、社会学和其他学科的交叉,对这些问题的一 种多原则途径正在发展。更重要的是,思考这些极其复杂问题的不同方法正在形成。抛开数学 的确定性,人们想写一个预言所有行为的方程,首先观察和寻找一个模式,用任何可能的手段 模拟这个模式(例如,这本书编入了遗传算法)。我相信,这种思维是有用的,因为我们正在 对管理越来越复杂软件项目的方法做科学观察。 1.4 起草:最小的方法 我首先声明,这一点没有证明过。我并不许诺—起草是起点,是其他思想的种子,是思 想试验,尽管这是我在大量思考、适量阅读和在开发过程中对自己和其他人观察之后形成的看 法。这是受我称之为“小说结构”的写作类的启示。“小说结构”出现在Robert McKee [2] 的教 学中,最初针对热心熟练的电影剧作家们,也针对小说家和编剧。后来我发现,程序员与这个 人群有大量的共同点:他们的思想最终用某类文本形式表达,表达的结构能确定产品成功与否。 有少量令人拍案称奇的上口小说,其他许多小说都很平庸,但有技巧,得到发行,大量不上口 的小说得不到发表。当然,小说要描述,而程序要编写。 作家还有一些在程序设计中不太出现的约束:他们一般单独工作或可能在两个人的组中工 作。这样,他们必须非常经济地使用他们的时间,放弃不能带来重要成果的方法。 M c K e e的两 个目标是将花费在电影编剧上的时间从一年减少到六个月,在这个过程中极大地提高电影编剧 的质量。软件开发者可以有类似的目标。 使每个人都同意某些事情是项目启动过程中最艰苦的部分。系统的最小性应当能获得最独 立的程序员的支持。 12 C + +编程思想 下载 [1] 另外一本好“前景”的书是Object Lessons Tom Love著, SIGS Books, 1993。 [2] Through Two Arts, Inc.,12021 Wilshire Blvd. Suite 868, Los Angeles, CA 90025。 1.4.1 前提 该方法的描述是建立在两个重要前提的基础上的,在我们采用该思想的其他部分时必须仔 细考虑这两个前提: 1) 与典型的过程语言(和大量已存在的语言)不同, C + +语言和语言性能中有许多防护, 程序员能建立自己的防护。这些防护意在防止程序员创建的程序破坏它的结构,无论在创建它 的整个期间还是在程序维护期间。 2) 不管分析得如何透彻,这里还有一些有关系统的事直到设计时还没有揭示出来,更多的 直到程序完成和运行时还没有揭示出来。因此,快速通过分析过程和设计过程以实现目标系统 的测试是重要的。根据第一点,这比用过程语言更安全,因为C + +中的防护有助于防止“面条” 代码的创建。 着重强调第二点。由于历史原因,我们已经用了过程语言,因此在开始设计和实现之前开 发组希望仔细地处理和了解每一微小的细节,这是值得表扬的。的确,当创建 D B M S时,彻底 地了解消费者的需要是值得的。但是, D B M S是一类具有良好形式且容易理解的问题。在这一 章中讨论的这类程序设计问题是w i l d - c a r d变体问题,它不只简单地重新形成已知解,而是包括 一个或多个w i l d - c a r d因素—元素,在这里没有容易理解的先前的解,而必须进行研究 [ 1 ]。在着 手设计和实现之前彻底地分析w i l d - c a r d问题会导致分析瘫痪,因为在分析阶段没有足够的信息 解决这类问题。解这样的问题要求在整个周期中反复,要冒险(以产生感性认识,因为程序员 正在做新事情,并且有较高的潜在回报)。结果是,危险由盲目“闯入”预备性实现而产生,但 是它反而能减少在w i l d - c a r d项目中的危险,因为人们能较早地发现一个特殊的设计是否可行。 这个方法的目标是通过建议解处理 w i l d - c a r d问题,得到最快的开发结果,使设计能尽早地 被证明或反证。这些努力不会白费。这个方法常常建议,“建立一个解,然后再丢掉它”。用 O O P,可能仍然丢掉一部分,但是因为代码被封装成类,不可避免地生产一些有用的类设计和 第一次反复中发展一些对系统设计有价值的思想,它们不需要丢掉。这样,对某一问题快速地 过一遍不仅产生对下一次分析、设计和实现的重复重要的信息,而且也为下一次的重复过程创 建了代码基础。 这个方法的另一性能是能对项目早期部分的集体讨论提供支持。由于保持最初的文档小而 简明,所以最初的文档可以由小组与动态创建该描述的领导通过几次集体讨论而创建,这不仅 要求每个人的投入,而且还鼓励开发组中的每个人意见一致。也许更重要的是,它能在较高的 积极性下完成一个项目(如先前注意到的,这是最基本的资源)。 表示法 作家的最有价值的计算机工具是字处理器,因为它容易支持文档的结构。对于程序设计项 目,程序的结构通常是由某形式的分离的文档来表述的。因为项目变得更复杂,所以文档是必 需的。这就出现了一类问题,如 B r o o k s[2] 所说:“数据处理的基本原则引出了试图用同步化方 法维护独立文档的傻念头—而我们在程序设计文档方面的实践违反了我们自己的教义。我们 典型的努力是维护程序的机器可读形式和一组独立可读的文档⋯⋯。” 好的工具应当将代码和它的文档联系起来。 我们认为,使用熟悉的工具和思维模式是非常重要的, O O P的改变正面临着由它自己引起 第1章 对象的演化 13 下载 [1] 我估计这样的项目的主要规则:如果多于一张 w i l d - c a r d,则不计划它要费多长时间和它花费多少。这里有太多 的自由度。 [2] The Mythical Man-Month, 出处同上。 的挑战。较早的O O P方法学已经因为使用精细的图形符号方案而受挫了。我们不可避免地要大 量改变设计,因为我们必须改变设计以避免棘手的问题,所以用很难修改的符号表示设计是不 好的。只是最近,才有处理这些图形符号的工具出现。容易使用设计符号的工具必须在希望人 们使用这种方法之前就有了。把这种观点与在软件设计过程中要求文档这一事实结合,可以看 出,最符合逻辑的工具是一个性能全面的字处理器 [ 1 ]。事实上,每个公司都有了这些工具(所 以试用这种方法不需要花费),大多数程序员熟悉它们,程序员习惯于用它们创建基本宏语言。 这符合C + +的精神,我们是建立在已有的知识和工具基础上的,而不是把它们丢掉。 这个方法所用的思维模式也符合这种精神。虽然图形符号在报告中表示设计是有用的 [ 2 ], 但它不能紧密地支持集体讨论。但是,每个人都懂得画轮廓,而且很多字处理器有一些画轮廓 的方法,允许抓取几块轮廓,很快地移动它们。这使交互集体讨论会上快速设计很完美。另外, 人们可以扩展和推倒轮廓,决定于系统中粒度的不同层次。(如后描述)因为程序员创建了设 计,创建了设计文档,所以关于项目状态的报告能用一个像运行编译器一样的过程产生。 1.4.2 高概念 建立的系统,无论如何复杂,都有一个基本的目的,它服务于哪一行业和它应满足什以基 本需要。如果我们看看用户界面、硬件、系统特殊的细节、编码算法和效率问题,那么我们最 终会发现它有简单和直接的核心。就像好莱坞电影中所谓的高概念,我们能用一两句话描述它。 这种纯描述是起点。 高概念相当重要,因为它为我们的项目定调。它是委派语句,不需要一开始就正确(可以 在完全清楚它之前完善这个论述或构思设计),它只是尝试,直到它正确。例如,在空中交通 控制系统中,我们可以从系统的一个高概念开始,即准备建立“控制塔跟踪飞机。”但是当将 该系统用于非常小的飞机场时,也许只有一个导航员或无人导航。更有用的模型不会使得正在 创建的解像问题描述那么多:“飞机到达、卸货、服务和重新装货、离去。” 1.4.3 论述(treatment) 剧本的论述是用一两页纸写的故事概要,即高概念的外层。计算机系统发展高概念和论述 的最好的途径可能是组成一个小组,该小组有一个具有写能力的辅助工具。在集体讨论中能提 出建议,辅助工具在与小组相连的网络计算机上或在屏幕上表达这些思想。辅助工具只起捉刀
本文档为【C++编程思想01】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_389449
暂无简介~
格式:pdf
大小:1MB
软件:PDF阅读器
页数:0
分类:互联网
上传时间:2012-02-22
浏览量:11