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