第1章 对象的演化
一、多态性的解释: 当处理类型层次结构时,程序员常常希望不把对象看作是某一特殊类型的成员,而把它看作基本类型成员,这样就可以编写不依赖于特殊类型的代码。在形体例子中,函数可以对一般形体进行操作,而不关心它们是圆、正方形还是三角形。所有的形体都能被绘制、擦除和移动,所以这些函数能简单地发送消息给一个形体对象,而不考虑这个对象如何处理这个消息。这样,新添类型不影响原来的代码,这是扩展面向对象程序以处理新情况的最普通的方法。
二、操作概念:OOP 程序像什么 一个写得很好的C + +程序一般要比功能相同的C 程序更简单和容易理解。程序员只会看到一些描述问题空间对象的定义(而不是计算机的描述),发送给这些对象的消息。这些消息表示了在这个空间的活动。面向对象程序设计的优点之一是通过阅读,很容易理解代码。
三、对象设计的五个阶段
下面是描述,不是方法。它简直就是对象期望的设计出现时的观察结果。
1) 对象发现这个阶段出现在程序的最初分析期间。可以通过寻找外部因素与界线、系统中的元素副本和最小概念单元而发现对象。如果已经有了一组类库,某些对象是很明显的。类之间的共同性(暗示了基类和继承类),可以立刻出现或在设计过程的后期出现。
2) 对象装配我们在建立对象时会发现需要一些新成员,这些新成员在对象发现时期未出现过。对象的这种内部需要可能要用新类去支持它。
3) 系统构造对对象的更多要求可能出现在以后阶段。随着不断的学习,我们会改进我们的对象。与系统中其它对象通讯和互相连接的需要,可能改变已有的类或要求新类。
4) 系统扩充当我们向系统增添新的性能时,可能发现我们先前的设计不容易支持系统扩充。这时,我们可以重新构造部分系统,并很可能要增加新类。 5) 对象重用这是对类的真正的重点测试。如果某些人试图在全新的情况下重用它,他们会发现一些缺点。当我们修改一个类以适应更新的程序时,类的一般原则将变得更清楚,直到我们有了一个真正可重用的对象。
四、对象开发原则
在这些阶段中,提出考虑开发类时所需要的一些原则:
1) 让特殊问题生成一个类,然后在解其他问题时让这个类生长和成熟。
2) 记住,发现所需要的类,是设计系统的主要内容。如果已经有了那些类,这个项目就不困难了。
3) 不要强迫自己在一开始就知道每一件事情,应当不断地学习。
4) 开始编程,让一部分能够运行,这样就可以证明或反驳已生成的设计。不要害怕过程语言风格的细面条式的代码—类分割可以控制它们。坏的类不会破坏好的类。
5) 尽量保持简单。具有明显用途的不太清楚的对象比很复杂的接口好。
第2章 数据抽象
一、库的重要性
库,简单地说就是一些人已经写的代码,按某种方式包装在一起。通常,最小的包是带有扩展名如L I B 的文件和向编译器声明库中有什么的一个或多个头文件。连接器知道如何在L I B文件中搜索和提取相应的已编译的代码。但是,这只是提供库的一种方法。在跨越多种体系结构的平台上,例如U N I X ,通常,提供库的最明智的方法是用源代码,这样在新的目标机上它能被重新编译。而在微软Wi n d o w s 上,动态连接库是最明智的方法,这使得我们能够利用新发布的D D L 经常修改我们的程序,我们的库函数销售商可能已经将新D D L 发送给我们了。所以,库大概是改进效率的最重要的方法。C + +的主要设计目标之一是使库容易使用。这意味着,在C 中使用库有困难。懂得这一点就对C + +设计有了初步的了解,从而对如何使用它有了更深入的认识。
二、声明与定义
“声明”向计算机介绍名字,它说,“这个名字是什么意思”。而“定义”为这个名字分配存储空间。无论涉及到变量时还是函数时含义都一样。无论在哪种情况下,编译器都在“定义”处分配存储空间。对于变量,编译器确定这个变量占多少存储单元,并在内存中产生存放它们的空间。对于函数,编译器产生代码,并为之分配存储空间。函数的存储空间中有一个由使用不带参数表或带地址操作符的函数名产生的指针。
三、一些函数:
1、 memcpy( ):一个字节一个字节地拷贝这个变量,第一个参数是memcpy( ) 开始拷贝字节的目的地址,第二和第三个参数分别是被拷贝变量的开始地址和要拷贝的字节数。
2、 realloc( ):把已经分配而又希望重分配的存储单元首地址作为它的第一个参数(如果这个参数为零,realloc( )分配一个新块),第二个参数是这个块新的长度,如果这个长度比原来的小,这个块将不需要作拷贝,简单地告诉堆管理器剩下的空间是空闲的。如果这个长度比原来的大,在堆中没有足够的相临空间,所以要分配新块,并且要拷贝内存。
3、void *malloc( size_t size ):The malloc function allocates a memory block of at least size bytes. The block may be larger than size bytes because of space required for alignment and maintenance information!
四、动态存储分配
动态内存分配函数是标准C 库的一部分,包括malloc( )、calloc( )、
realloc( )和free( )。,C 堆管理器相当重要,它给出内存块,对它们使用free( )时就回收它们。没有对堆进行合并的工具,如果能合并就可以提供更大的空闲块。如果程序多次分配和释放堆存储,最终会导致这个堆有大量的空闲块,但没有足够大且连续的空间能满足我们对内存分配的需要。但是,如果用堆合并器移动内存块,又会使得指针保存的不是相应的值。
五、C单元的编译过程 编译每个单元--〉连接各个目标文件
1)每个独立的C 文件就是一个处理单元。就是说,编译器在每个处理单元上单独运行,而编译器在运行时只知道这个单元。这样,用包含头文件提供信息是相当重要的,因为它为编译器提供了对程序其他部分的理解。在头文件中的声明特别重要,因为无论是在哪里包含这个头文件,编译器都会知道要做什么。例如,若在一个头文件中声明void foo(float),编译器就会知道,如果我们用整型参数调用它,它会自动把i n t 转变为f l o a t 。如果没有声明,这个编译器就会简单地猜测,有一个函数存在,而不会做这个转变。
2),编译器创建一个目标文件,带有扩展名.o 或.obj 或类似的名字。必须再用连接器将这些目标文件连同必要的启动代码连接成可执行程序。在连接期间,所有的外部引用都必须确定用对应的实际地址,用这些地址替换这些外部引用。
六、头文件形式:
在C++ 中,头文件的使用变得非常清楚。它们对于每个程序开发是强制的,在它们中放入非常特殊的信息:声明。头文件告诉编译器在我们的库中哪些是可用的。因为对于C P P文件能够不要源代码而使用库(只需要对象文件或库文件),所以头文件是存放接口规范的唯一地方。头文件是库的开发者与它的用户之间的合同。它说:“这里描述的是库能做什么。”它不说如何做,因为如何做存放在C P P 文件中,开发者不需要分发这些描述“如何做”的源代码给用户。为了恰当地组织代码和写有效的头文件,有一些问题必须知道。第一个问题是将什么放进头文件中。基本规则是“只声明”,也就是说,对于编译器只需要一些信息以产生代码或创建变量分配内存。是因为,在一个项目中,头文件也许会包含在几个处理单元中,而如果内存分配不止一个地方,则连接器会产生多重定义错误。这个规则不是非常严格的。如果在头文件中定义“静态文件”的一段数据(只在文件内可视),在这个项目中将有这个数据的多个实例,编译器不会报错。基本上,不要在头文件中做在连接时会引起混淆的任何事情。(另外见Effective C++)
七、嵌套结构:简单地两次使用范围分解运算符,以指明这个嵌套struct 的名字。stack::link::initialize( ) 函数取参数并把参数赋给它的成员们。
本文地址:http://com.8s8s.com/it/it29626.htm