




已阅读5页,还剩12页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C+程序设计-课程学习总结 学院: 电子与电气工程学院 班级: 电子091班 学号: 0903741021 姓名: 石楚雄 任课老师: 王骏 完成日期: 2012年05月25日 15目录前言21、 编程规范31.1 变量的命名和函数的命名规则 31.2 代码的排版布局41.3注释 42、 I/O流42.1 cout的输出缓存问题 5 2.1-1 交互式输入输出顺序问题 52.1-2 cout 中多表达式的输出顺序问题72 .2 cin 的输入缓存问题 93、 程序结构 103.1 外部存储类型103.2 静态全局变量和静态函数 114、 数组与指针115、 堆与拷贝构造函数 126、 总结 157、 参考文献16前言C+从C进化而来,是C语言的超集。C+是一门高效实用的程序设计语言,它既可以进行过程化程序设计,也可进行面向对象程序设计。C+语言强调对高级抽象的支持。C+实现了对类的封装、数据隐藏、继承及多态,使得其代码容易维护及高度可重用。随着C+渐渐成为ANSI标准,这种新的面向对象程序设计语言迅速成为程序员最广泛使用的工具。几乎在所有的计算机研究和应用领域,都能看到C+的影子。本学期我们学习了C+程序设计这门课程,在原有C语言的基础知识之上,初步接触C+时感到比较简单易懂,和C语言在程序结构本质上一致,都是用函数驱动机制实现的。随着课程学习的深入,发现C+在程序结构的本质上确实是与C语言一致的,都是用函数驱动机制实现的;不过C+与C语言还是很多不同的地方,C+有自己的优势,它的难度也逐渐浮现出来。下面简单从几个方面谈谈我对C+的学习心得。1、 C+编程规范学习一种语言就会有一种相应的规范,C语言是,C+也是。下面首先就简单谈一下C+编程规范中应值得注意的地方。1.1 变量的命名和函数的命名规则标识符应当直观且可以拼读,可望文知意,不必进行“解码”。标识符最好采用英文单词或其组合,便于记忆和阅读。切忌使用汉语拼音来命名。程序中的英文单词一般不会太复杂,用词应当准确。例如不要把CurrentValue 写成NowValue。标识符的长度应当符合“min-length & max-information”原则。一般来说,长名字能更好地表达含义,所以函数名、变量名、类名长达十几个字符不足为怪。那么名字是否越长约好?不见得! 例如变量名maxval 就比maxValueUntilOverflow好用。所以,当变量名较长时可以用部分首字母组成,含义也比较清晰。程序中不要出现标识符完全相同的局部变量和全局变量,尽管两者的作用域不同而不会发生语法错误,但会使人误解。变量的名字应当使用“名词”或者“形容词名词”。例如:float value;float oldValue;float newValue;全局函数的名字应当使用“动词”或者“动词名词”(动宾词组)。类的成员函数应当只使用“动词”,被省略掉的名词就是对象本身。例如:DrawBox(); / 全局函数box-Draw(); / 类的成员函数1.2 代码的排版布局我个人认为代码排版布局很重要,一个好的程序员就应该有好的排版格式。好的排版整齐,清晰明了。一个毫无规则的代码让人看着就会觉得不舒服,不愿意看。缩进空格使用Tab缩进,使代码对齐,这是我个人写代码的习惯。1.3注释应使用 C+ 风格注释分界符/,而非 C 风格的/*.*/。C+ 风格的注释更易理解,它减少了由于偶然缺少一个注释结束分隔符而造成大量代码被注释掉的风险。注释应紧贴它们所要注释的代码;它们使用相同的缩进,使用一个空注释行接于代码之后。对多行连续语句的注释应置于语句的上方作为语句的介绍性说明。而对单个语句的注释应置于语句的下方。说完了主要的编程规范接下来谈谈I/O流控制。二、I/O流在C程序中,printf和scanf是标准的输入输出函数,在头文件stdio.h中声明了这两个函数。在C+面向对象程序设计中,I/O流代替了它们。在过程化程序设计中,printf和scanf在使用习惯上,可作为C+流的一个补充。I/O流是输入或输出的一系列字节,当程序需要在屏幕上显示输出时,可以使用插入操作符“”向cout输出流中插入字符。例如:Cout”从cin输入流中抽取字符。例如:int myAge;CinmyAge;2.1 cout的输出缓存问题2.1-1 交互式输入输出顺序问题在交互式的应用程序中,常常希望在屏幕上出现提示信息后, 用户再键入相应的数据作出响应。即程序在处理输入操作前先要显示提 示信息。但在使用不当的情况下, 这种交互的效果不但达不到, 反而会出现令人费解的现象, 先来看下面程序1所示的简单例子。程序1#include #include void main() char ch;coutinput ch:n;ch=getchar();程序2#include #include void m ain() char ch;coutch;运行程序1后发现, 程序并未如设想的那样,先输出提示信息,后再接 受输入;而是在输入数据之后才输出此前的那条提示信息。为什么输出顺序颠倒呢? 其根源在于C +的I/O流内部带有缓冲区, 而cout 就是一个I/O流ostream流类的一个标准的输出对象。在有输出缓的情况下,输出并不都是即时的。只有当输出缓存已满、程序明确要求、或程序结束时,输出缓存的信息才会显示出来。下面换一种输入方式,将程序1中的输入语句改为用cin实现,如程序2所示。运行该程序的结果是输出顺序不再是程序1的颠倒顺序, 而是正常的顺序了。原来, C +提供了成员函数tie来同步istream 和ostream的操作,以保 证输出在输入之前显示出来。即调用语句cin.tie(& cout);可以把cout 连接到cin。事实上 , 无须显式地在代码中使用此调用语句, C +会 自动执行该调用来创建用户的标准输入/输出环境。这就是为什么程序2能得以正常执行的原因。那么如何使程序1中的cout在没有和getchar()输入“捆绑”在一起的前提下,也能按正确的顺序输入输出,也就是说无论输出缓存是否已满,都能即时输出,这就需要通过手动刷新缓冲区的方式来强制要求输出缓存的信息。具体可以用流操作符endl 或者flush 来清空输出缓存, 以达到即时输出的目的。见程序3。程序3:#include #include using nam espace std;void main() char ch;coutflushinput ch:n; /或者改为coutinput chendl;ch=ge tcha r();2.1-2 cout 中多表达式的输出顺序问题cout允许其后插入多个表达式, 但在许多C +系统中, 多个表达式之间的求值顺序却出乎意料。观察程序4 的运行结果,程序4:#include int f1() coutf1t;return 1;int f2() coutf2t;return 2;void m ain() coutf1()tf2()endl; 我们看到, 程序运行结果不是预想的:f1 1 f2 2而是f2 f1 1 2程序5:#include int f1() coutf1t;return 1;int f2() coutf2t;return 2;void m ain() printf(% dt% dt,f1(),f2(); 如果将主函数改为如程序5 所示的形式, 则程序运行结果为:1 2 f2 f1可以看出, 程序5 先输出了printf 的结果, 然后再输出cout的结果。而按程序本身的顺序, 应该是cout 的执行在前, 返回给printf 的结果在后。这也印证了cout 在使用上要注意输出缓存的问题。另一方面f2 , f1的输出顺序与程序4一样, 都和预想的相反。其原因是在许多C + +系统中, 无论是在cout 的“ ”运算中, 还是printf 的表达式求值中, 多表达式的求值顺序都是自右向左进行的。所以在程序4里cout 的多表达式输出中, 表达式送入输出缓冲区的顺序是自左向右的, 而表达式的求值顺序则是自右向左进行的。因此, 在多表达式输出中, 不要将相互有值依赖的表达式放到一个cout 语句中, 也尽量不要将带缓冲的cout 和不带缓冲的printf 这两种输出混用, 否则会带来不可预料的结果。2 .2 cin 的输入缓存问题通过标准输入流cin 输入数据时, 提取符“ ”能自动识别其后的数据类型, 所以一旦输入的数据类型与规定的类型不相匹配, 流提取操作符就会设置流的failbit 状态位, 输入的数据就不会被提取, 从而保证了输入的安全性。但有时程序需要对非法类型的数据进行处理, 如在用cin 对自定义类型进行操作时,当发现输入有错时需要予以纠正, 以便重新输入, 这时就需要使用clear()函数将流的标记更改为正确, 如程序6 所示。程序6# in clu d e void main () int a ;while (1) cin a ;if(!cin ) cout dateeror! Input again !n ;cin.clear();/cin.get();else break;运行程序6却发现, 在输入非法数据的时候, 程序并不能重新接受数据, 而是陷入了死循环。可见通过clear()函数将流的标记更改为正确还不够, 原因是cin 是类型敏感的输入, 对非法类型的数据是不提取的; 同时cin又是缓冲式输入,不被提取的非法类型数据便一直留在缓冲区内。这时只有通过get()成员函数清除掉缓冲区的非法类型数据后, cin才能重新提取正确的数据并送入变量, 否则将会陷入死循环所以, 上述程序必须将被注释掉的那条cin.get()语句变为有效代码才能达到目的。三、程序结构3.1 外部存储类型一个程序在很小的规模下,可以用一个源文件来完整表达。可是,一般具有应用价值的程序是由多个源文件组成。根据C+程序的定义,其中只有一个源文件具有主函数main(),而其他的文件不能含有main(),否则程序不知道该从何处开始执行。在多个源文件之间,是通过声明数据或函数为外部的(extern)来沟通的。但要注意所有函数的声明一般都放在源文件的开始位置。我们应该记住,带extern的变量说明是变量声明,不是变量定义!3.2 静态全局变量和静态函数在全局变量和函数前加一个static,使该变量和函数只在这个源文件中可用,称之为全局静态变量和全局静态函数。我们应该记住静态全局变量和函数只对该文件可用,对其他源文件是无效的。四、数组与指针指针与数组是是C+学习中重要部分,很多编程新手常常认为“数组和指针是相同的”。不幸的是 ,这是一种非常危险的说法,并不完全正确。两者既有相似之处,也有很多不同的地方。 首先,数组和指针最大的区别是访问数据的方式。众所皆知数组是用来存放数据的,而指针里放的是数据的地址。所以数组直接访问数据,而指针是间接的访问数据。 char a = abcde; char *p = abcde; 对于数组a,假设字符串的首地址是1234,则当我们要求a2时,编译器直接进行1234(首地址)+2(偏移量)操作,然后取得地址(1234+2)的内容c实现对a2的访问。但是对于指针,由于指针里面存放的是字符串首地址,所以必须先取得首地址再进行和数组一样的操作。这里假设指针p本身的地址是1357,编译器会先到1357地址中取得字符串的首地址1234,然后取地址(1234+2)的内容实现p2的操作(下面将会讲到此操作)。 另外一个重要的区别,数组是系统在初始化时自动为我们分配空间的,一般放在栈区, 且由系统自动对它删除。而指针是程序员本身用malloc()函数动态分配到堆区,并用free()函数将其释放。 数组的大小初始化后是固定的且数据类型必须相同。在上面的列子中可以看出数组和指针都可以在它们的定义中用字符串常量进行初始化。尽管看上去一样,底层的机制却不同。定义指针时,编译器并不为指针指向的对象分配空间,它只是分配指针本身的空间。在ANSI C中,初始化指针时所创建的字符串常量被定义为只读,不能对它进行修改。与指针相反,字符串常量初始化的数组是可以修改的。比如:strncpy(a,fdg,3)。就将数组a的值修改为:fdgde。 五、堆与拷贝构造函数C+中,堆分配的概念得到了扩展,不仅c+的关键字new和delete可以分配和释放堆空间,而且通过new建立的对象要调用构造函数,通过delete删除对象也要用析构函数. C+程序的内存格局通常分为四个区: (1)全局数据区;(2)代码区;(3)栈区;(4)堆区(自由存储区)。全局变量、静态数据、常量存放在全局数据区,所有类成员函数和非成员函数代码存放在代码区,为运行函数而分配的局部变量、函数参数、返回数据、返回地址等存放在栈区,余下的空间都被作为堆区。函数“ void *malloc(size_t);”和“void free(void *)”在头文件malloc.h中声明,而操作符new和delete是c+语言的一部分,无须包含头文件。操作堆内存时,如果分配了内存,应有责任回收它,否则运行的程序将会造成内存泄漏. 需要new和delete的原因,从c+的立场上看,不能用malloc()函数的一个原因是,它在分配空间的时候不能调用构造函数。类对象的建立是分配空间、构造结构以及初始化的三位一体,它们统一由构造函数来完成。从程序设计的需要来看,在分配内存申请的时候,总是知道分配的空间派什么用,而且分配空间大小总是某个数据类型(包括类类型)的整数倍。因而c+用new 代替c的malloc。 分配堆对象,堆对象的作用域是整个程序生命期,所以除非程序运行完毕,否则堆对象作用域不会到期。从堆上分配对象数组,只能调用默认的构造函数,不能调用其他任何构造函数。如果该类没有默认构造函数,则不能分配对象数组。一般来说,堆空间相对其他内存空间比较空闲,随要随拿,给程序运行带来了较大的自由度。使用堆空间往往由于: (1)直到运行时才能知道需要多少对象空间; (2)不知道对象的生存期到底有多长; (3)直到运行时才知道一个对象需要多少内存空间。 拷贝构造函数,可用一个对象去构造另一个对象,或者说,用另一个对象值初始化一个新构造的对象。对象作为函数参数时,也要涉及对象的拷贝。对象的类型多种多样,有些对象还可申请系统资源。 类定义中,如果未提供自己的拷贝构造函数,则c+提供一个默认的拷贝构造函数。C+提供的默认拷贝构造函数工作的方法是,完成一个成员一个成员的拷贝。如果成员是类对象,则调用其拷贝构造函数或者默认拷贝构造函数。 在默认拷贝构造函数中,拷贝的策略是逐个成员依次拷贝。但是拷贝构造函数简单地制作了一个该资源的拷贝,而不对它本身分配,就面临一个麻烦的局面:两个对象都有同一个资源。当对象析构时,该资源将经历两次资源返还。浅拷贝:创建p2时,对象p1被复制给了p2,但资源并未复制,p1和p2指向同一个资源。深拷贝:创建p2时,对象p1被复制给了p2,同时资源也作了复制,p1和p2指向不同的资源。堆内存不是唯一需要拷贝构造函数的资源,但它是最常用的一个。经验:如果你的类需要析构函数来析构资源,则它也需要一个拷贝构造函数。当函数返回一个对象时,要创建一个临时对象以存放到返回的对象。一般规定,创建的临时对象,在整个创建它们的外部表达式范围内有效,否则无效。可以直接调用构造函数产生无名对象。无名对象可以作为实参传递给函数,可以拿来拷贝 构造一个新对象,也可以初始化一个引用的声明。无名对象的三种典型用法:初始化引用。如:Student & refs=Student(“Randy”);初始化对象定义。如:Student s=Student(“Jenny”);函数参数。如:fn(Stude
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 二零二五年度市政道路监理合同终止及验收交接协议
- 二零二五年度房地产抵押贷款还款计划合同
- 2025版文化主题咖啡馆品牌授权经营合同
- 2025年电子商务运营师专业技能笔试模拟题及答案
- 2025年度工业废气处理设备租赁合同样本
- 2025版新能源车质押借款合同
- 二零二五年度绿色建筑示范项目单位施工合同
- 2025电脑租赁与远程技术支持服务合同
- 二零二五年度养老机构代建及服务合同
- 二零二五年度租赁合同示范(含租赁房屋租赁合同终止权及责任)
- 混凝土结构设计原理教学教案
- 民间文学(全套课件)
- 专升本00465心理卫生与心理辅导历年试题题库(考试必备)
- 既有重载铁路无缝线路改造及运维技术探索
- 2022年教师副高职称评答辩范文(七篇)
- 高压罗茨风机选型参数表
- 中国监察制度史
- 架桥机日常检查记录表架桥机验收及试吊安全检查表
- 屠宰加工企业组织机构职能分配表正式版
- 善交益友、乐交诤友、不交损友(课堂PPT)
- 消防水泵房上墙制度
评论
0/150
提交评论