330 likes | 412 Views
C++ 程序设计教案. (1) 张海涛 . 第 1 节 面向对象的方法来自实践. 1 面向对象方法的由来 2 OO 方法的引入 3 程序设计的质量因素 4 设计中常见的问题 5 程序设计常识与技巧. 1 面向对象方法的由来. 1-1 早期程序设计语言的发展 Fortran, Cobol, APL, C 等出现是为了方便的编写代码。 特点: 方便, 易学,小巧 简洁的设计是最好的技巧. 1 面向对象方法的由来. 1-2 现代程序设计语言 C++, Ada, Java 等与传统的语言相反,显得十分庞大,难以学会。 特点:
E N D
C++程序设计教案 (1) 张海涛
第1节 面向对象的方法来自实践 1 面向对象方法的由来 2 OO方法的引入 3 程序设计的质量因素 4 设计中常见的问题 5 程序设计常识与技巧 my email:haitao_mail@hotmail.com
1 面向对象方法的由来 1-1 早期程序设计语言的发展 Fortran, Cobol, APL, C 等出现是为了方便的编写代码。 特点: • 方便, 易学,小巧 • 简洁的设计是最好的技巧 my email:haitao_mail@hotmail.com
1 面向对象方法的由来 1-2 现代程序设计语言 C++, Ada, Java 等与传统的语言相反,显得十分庞大,难以学会。 特点: • 庞杂难学 • 编写程序比原来要长的多! my email:haitao_mail@hotmail.com
1 面向对象方法的由来 1-3 Why? • 程序员: 定义+声明+描述+许多困难 ==〉保证代码的一致性 • 现代语言: 不一致性是语法错误! 代码可以自我文档化 (业界趋势)! 语言的本身没有任何的优点 (代码可能会一样的糟糕) my email:haitao_mail@hotmail.com
1 面向对象方法的由来 1-4 面向对象方法与程序复杂性的关系 • OOP编写小程序时 “弊大于利”, 适合复杂程序 • 程序设计的复杂性来源 ① 应用本身的复杂性 (程序员无法决定) ② 程序实现的复杂性 大大增加 (程序员可以控制) 返回 my email:haitao_mail@hotmail.com
2 面向对象方法的引入 2-1 面向对象方法的出发点 • 尽可能的模拟人的思维方式去解决问题 • 以对象为中心: 特殊 –〉 归纳 -〉一般 - 〉演绎 -〉特殊 • 问题空间与解空间的矛盾 • 客观世界的动态特性 —— 解空间的复杂算法 • 运动与实体的统一 —— 解空间程序与数据的分离 my email:haitao_mail@hotmail.com
2 面向对象方法的引入 2-2 面向对象方法的简单概括 • 客观世界都是由对象组成的。 • 所有的对象都可以划分为抽象的类。 • 可以按基类和派生类的关系组成类的层次结构。 • 对象间的通信仅通过消息传送机制。 my email:haitao_mail@hotmail.com
2 面向对象方法的引入 2-3 Coad & Yourdon的定义 (1991) Object-Oriented= Objects +Classfication +Inheritance +Communication with messages my email:haitao_mail@hotmail.com
2 面向对象方法的引入 2-4 类和对象的概念 • 对象(Object):一个包含数据结构和施加其上的操作的封装体。 • 类(Class):对具有相同属性和行为的一个或多个对象的描述。 • 类中定义的数据(实体的性质),称为属性(Attribute) • 类中的操作(服务),称为方法(Method) my email:haitao_mail@hotmail.com
2 面向对象方法的引入 2-5聚合关系(Aggregation) • 是“整体——部分”的关系,它反映了对象之间的构成关系;是类与类关联的特例。 • 相关概念 • 关联:对象之间相互依赖和作用的关系 • 举例: 汽车——发动机 电脑——显示器 my email:haitao_mail@hotmail.com
2 面向对象方法的引入 2-6继承关系(Inheritance) • 是“一般——特殊”的关系,它反映了基类与若干个互不相容的子类之间的分类关系。 • 相关概念——继承: • (广义)直接获得已有的特征和性质,而不必重新定义 • (狭义)子类自动的共享基类中定义的数据与方法一种机制 • 举例: 汽车——轿车 电脑——笔记本电脑 my email:haitao_mail@hotmail.com
2 面向对象方法的引入 2-7练习 • 分析下列对象之间的关系 “家具、沙发、衣柜、电视柜、服装、衬衣,裤子、家用电器、电视、DVD机、组合音响、功放和音箱” my email:haitao_mail@hotmail.com
2 面向对象方法的引入 2--8消息(Message) • 消息:对象之间通信的一种构造。 • 组成部分: • 接收消息的对象 • 消息名 • 若干个变元 返回 my email:haitao_mail@hotmail.com
3 程序设计质量的因素 3-1 高内聚性的函数: • 函数的命名:用函数的完成的任务(动词短语)。 • 如果出现命名的困难情况 —— 多个动词出现,那么内聚性很可能较差。 例如: insertItem(); //ok; insertOrRemoveItem; //暴露了函数的低内聚性 注意:也不要把函数分成小块,造成接口泛滥! my email:haitao_mail@hotmail.com
3 程序设计质量的因素 3-2 接口的低耦合度: • 期望:尽量减少函数接口中的元素数量; • 可以通过合并对相同数据的操作来减少接口处错的情况; • 找到内聚和耦合的结合点。 my email:haitao_mail@hotmail.com
3 程序设计质量的因素 3-3 经典设计案例—Booch(客户机与服务器的连接方案) • 面向对象方法——函数与数据的绑定 客户对象 服务器对象 服务器方法 客户方法 数据 数据 客户方法 服务器方法 客户方法 服务器方法 客户方法 返回 my email:haitao_mail@hotmail.com
4 程序设计常见问题--命名冲突 开发小组 • 原因1:在一个C++程序中函数的名字是唯一的。 • 原因2:当开发人员较多时,保持命名一致性是一件很困难的事情。 • 原因3:命名是有一定的规定标准的。 解决: 面向对象的方法缓解了这一问题:它允许在不同类中声明同名的函数! 返回 my email:haitao_mail@hotmail.com
5 程序设计的常识与技巧 5-1 稳定性是第一原则: • 程序是否稳定可靠是可用的首要条件 • 稳定性不只是在一般状况下,而是在各种情况下 例如: 网站在10个用户连接点击正常,不代表100个用户同时连接点击也正常; 可以在网上找一些测试网站,测一下自己做的网站的性能。 my email:haitao_mail@hotmail.com
5 程序设计的常识与技巧 5-2 可维护性和可读性: • 写程序时要考虑可读性,为以后自己维护或同事维护提供方便; • 影响可读性的原因: 使用大量的递归; 来回的跳转– 关于Goto语句; 不常用的算法等。 my email:haitao_mail@hotmail.com
5 程序设计的常识与技巧 5-3 可移植性的考虑: • 不只要在windows中正常运行,还要考虑Linux, Unix等系统是否可以运行; • 影响可移植性的原因: 例如,在C程序中使用大量的库函数造成了不统一; Java的统一性正在逐步解决这些问题。 my email:haitao_mail@hotmail.com
5 程序设计的常识与技巧 5-4好的代码风格 — 整齐,易懂,但未必高效: • 函数和变量取名标准; • 代码要对齐(tab=4),不要太多缩进; • 函数尽量少用参数,一定要校验每个函数的返回值; • 在函数开始位置定义和声明所有的变量, 对变量初始化; • 注意不要写太长的函数; • 慎用“宏”,用则大写之;(例如:#define MY_MACRO 25) my email:haitao_mail@hotmail.com
5 程序设计的常识与技巧 5-5 C/C++语言编码书写的小技巧: If (data_Found) { do_Something(); } • 技巧:“即使是单句程序也用 { } ” 返回 my email:haitao_mail@hotmail.com
匈牙利命名法(Hungarian Notation) 规则:[Prefix]-BaseTag-Name 其中标准的Prefix (可选) 有: p – 指针,rg – 集合,c – 计数器,h – 句柄 另外约定: C++成员变量由m开头:如,m_fInit 全局变量由g开头:如, g_fFlag my email:haitao_mail@hotmail.com
匈牙利命名法(Hungarian Notation) 其中BaseTag—数据类型有(C++): void – v int – i BOOL – f UNIT – ui BYTE – b CHAR – ch WCHAR – wch ULONG- ul LONG – l DWORD – dw HRESULT – hr DWORD- w …… 返回 my email:haitao_mail@hotmail.com
关于Goto语句的使用 使用原则: • 单入口和单出口可以使用Goto; • 尽量不用多于1个的Goto语句标记; • 保证使用Goto不产生代码“死角”; • 一般不往回跳转,可以向前跳转。 返回 my email:haitao_mail@hotmail.com
关于函数的长度 IBM公司在1986年统计数据表明 • 最容易出错的函数是超过500行的函数。 1991年统计数据表明 • 少于143行的函数的出错率比长函数的出错率要低2.4倍! 返回 my email:haitao_mail@hotmail.com
关于变量初始化的问题 大多数情况,变量不必初始化,但是: • 问题1:在程序中间的初始赋值语句被跳过; • 问题2:在初始赋值前就开始访问该变量; • 问题3:有些语言的初值是随机的(C/C++),无法判定初值。 my email:haitao_mail@hotmail.com
关于变量初始化的问题 例1: HRESULT hr; // 因此:第一句改为 HRESULT hr=S_OK; LPSTR str = (LPSTR) LocalAlloc (LPTR, size) // 内存分配不一定成功 if (str) { …… hr = S_OK; } // 这句加 else { hr=E_FAIL; } return hr; ?? 若hr初值恰巧=S_OK,那程序就有问题了 ?? my email:haitao_mail@hotmail.com
关于变量初始化的问题 例2: BOOL myBadFunc( USHORT x) { while (--x >=0) { …… } rerurn TRUE; } ?? X的初值永远不为负值,所以,程序陷入死循环。 返回 my email:haitao_mail@hotmail.com
关于函数返回值的问题 例:…… wcscpy ( wcServerIP, WinsAnsiToUnicode(cAddr,NULL) ); …… 注: WinsAnsiToUnicode是一个将Ansi串转换为新的Unicode串的一个API函数。 问题1:一旦WinsAnsiToUnicode()函数失败则返回NULL, 但是wcscpy()函数却没有对NULL的处理—— 导致系统崩溃; 问题2:wcscpy()函数没有回收WinsAnsiToUnicode()函数所分配的内存空间——导致内存越占越多,进而无法继续运行。 my email:haitao_mail@hotmail.com
关于函数返回值的问题 改为: …… LPWSTR tmp; tmp= WinsAnsiToUnicode(cAddr,NULL) ; if (tmp != NULL ) { wcscpy ( wcServerIP, tmp ); WinsFreeMemory ( (PVOID )tmp ); } else { return ( E_NOT_ENOUGH_MEMORY ); } 返回 my email:haitao_mail@hotmail.com