收藏 分享(赏)

C++面向对象程序设计(word版).doc

上传人:dreamzhangning 文档编号:2727497 上传时间:2018-09-26 格式:DOC 页数:20 大小:93.50KB
下载 相关 举报
C++面向对象程序设计(word版).doc_第1页
第1页 / 共20页
C++面向对象程序设计(word版).doc_第2页
第2页 / 共20页
C++面向对象程序设计(word版).doc_第3页
第3页 / 共20页
C++面向对象程序设计(word版).doc_第4页
第4页 / 共20页
C++面向对象程序设计(word版).doc_第5页
第5页 / 共20页
点击查看更多>>
资源描述

1、C+面向对象程序设计主讲人:张位勇计算机与信息科学系Email:Tel:15886402018面向:计算机本专科专业 讲授学时:理论学时 44实验学时 12 预修课程: 计算机导论 程序设计基础(可选) 本课程的教学目标是使学生系统掌握面向对象编程的基本原理,着重掌握面向对象编程原理,结合 C+开发语言进行面向对象编程理论的实践,培养学生独立获取知识、系统分析和解决问题的能力 。要求掌握面向对象程序设计的基本技术及思想,掌握统一建模语言,了解改良的软件开发过程,对大中型软件的开发设计有较好的理论和技术依据。1、概述介绍面向对象程序设计诞生的原因以及相关特征,对 C+与 C 的进行了比较,并对U

2、ML(Unified Modeling Language)进行了简单的说明。2、 C+编程基础主要讲解基本程序结构、变量和输入输出(IO) ,并对注释、算术运算符、递增运算符、数据转换以及库函数做了简单介绍。3、循环和选择对循环和选择两类控制语句以及关系和逻辑运算符做了详细介绍,并对运算符的优先级做了相关讨论。4、结构重点介绍结构相关概念以及特征,并对另外一种可以自定义数据类型的方法枚举做了相关说明。5、函数在掌握函数基本概念和使用基础上,对引用、重载以及内联等相关概念做了深入的讲解。6、 对象和类本章为重点,对类和对象的相关实现细节做了深入探讨,最后对使用面向对象程序设计的相关方法做了简单讨

3、论。7、数组和字符串研究在类中作为数据成员的数组以及用来记录对象的数组,并介绍了实现字符串的几种方法。8、运算符重载对一元和二元运算符的重载实现做了详细说明,同时对 UML 的第一个特征类图做了简单的介绍。9、 继承本章为重点,涉及了继承相关细节问题。在介绍一些具体实例后,对继承的相关特点做了详细的讨论。10、指针从基本概念开始,逐步介绍指针,直到相关复杂应用。11、虚函数本章为重点,内容覆盖了虚函数、友元函数、静态函数、拷贝构造函数、UML 对象图以及this 指针等 C+高级特征。12、流和文件主要讨论 C+的流类。介绍如何使用 C+的流来执行与文件相关联的活动,并对 C+中与文件相关的特

4、征做了简单描述。13、多文件程序全面讨论多文件程序。了解文件间通信如何进行的,以及头文件是如何描述的等内容。14、模板和异常重点介绍 C+的两个高级特性:模板(template)和异常(exception) 。15、标准模板库主要描述 STL 及其使用方法,并讨论最常见的容器和算法。16、面向对象软件开发讨论统一开发过程以及如何应用于实际程序。教材:Robert Lafore 著,邓子梁等译:C+面向对象程序设计(第四版) ,中国电力出版社,2004.2主要参考书:Stanley B.Lippman 著,李师贤等译: C+ Primer 中文版(第 4 版) ,人民邮电出版社,2006.6最终

5、成绩=考试成绩+平时成绩平时成绩:实验成绩作业出勤加减分课程设计成绩1.1 面向对象程序设计诞生的原因1.1.1 面向过程语言每条语言告诉计算机该做什么,程序就是一个指令序列。划分为函数一个面向过程的程序被划分为多个函数,每个函数都有明确的功能定义,对程序中的其他函数也定义了明确的接口。将程序划分为函数的思想被进一步扩充,即把大量的函数聚集到一个称为模块(module)的实体内。把程序划分为函数和模块是结构化程序设计的基石之一。结构化程序设计的问题函数能够不受限制地访问全局性数据;函数和数据之间缺乏联系。不受限制的访问一个过程化的程序中,有两种数据:局部数据和全局数据。在大型程序中,有很多的函

6、数和全局数据项,从而导致了函数和数据之间数目巨大的潜在连接。这会导致麻烦:首先,它使程序结构很难概念化;其次,它使得程序很难修改。全局数据项的一个改变会导致所有访问这个项的函数重写。现实世界建模面向过程范型中,数据与函数分离为现实世界提供了一个粗劣的模型。在现实世界中,必须处理像人和汽车等的对象,这些对象都有其属性和行为。属性即程序中的数据,都有其特定值。行为即处理这些数据的方法,即函数。只有数据和行为两者一起,才能有效地构造现实世界中对象的模型。1.1.2 面向对象方法面向对象语言的基本思想即把数据和行为合并到一个单元中,即对象。对象的函数在 C+中叫做成员函数(member functio

7、n),它提供了访问该对象内数据的惟一途径。将数据和它的函数装进一个实体,被称为封装。1.2 面向对象语言的特征1.2.1 对象当采用一门面向对象语言来解决程序设计问题时,不用再考虑如何将问题划分为函数,而是应该如何划分为对象。用对象来思考问题,更能够与现实世界中的实体对象进行匹配。PS:举例1.2.2 类在 OOP 中对象是类 (class)的成员。类定义了一件事物的抽象特点,指出了这个类的对象包含了哪些数据和函数。定义类并不会创建任何对象。对象被称为类的实例(instance)。1.2.3 继承在某种情况下,一个类会有子类。子类比原本的类(称为父类)要更加具体化。子类会继承父类的属性和行为,

8、并且也可包含它们自己的。 继承缩短了面向对象程序,并且使得程序各成分之间的关系更加清晰。1.2.4 可重用性一旦一个类通过编写、创建和调试等步骤,就可以被分发给其他程序员,以便他们能在各自的程序中使用它,这就是可重用性(reusability) 。继承为可重用性思想提供了重要的扩展,程序员可以使用已存在的类,并且不加修改就可以增加其他的特征和功能。1.2.5 创建新的数据类型1.2.6 多态性和重载1.3 C+和 CC+源于 C 语言,它是 C 语言的一个超集,也称带类的 C。1.4 基础知识第 2 章至第 5 章是 C+中与“传统”有关的方面,也可以在 C 语言中找到它们的存在,从第6 章“

9、对象和类” 开始 OOP 方面的专业讨论。1.5 统一建模语言(UML)UML(Unified Modeling Language)是为计算机程序建模的一门图形化语言。建模就是创建某事物的简化表示。UML 就是在考虑实际的代码细节之前,用图示将程序结构在很高的层次上表示出来。UML 最重要的部分是一个含有不同种类图的图集。它不是一个软件开发过程,只是一种研究程序结构的方法。本章主要介绍以下三个方面的基础知识:基本程序结构变量输入/输出(I/O)2.1 准备开始源文件是文本文件(扩展名为.CPP)本书程序可以在 Microsoft 编译器或者 MS-DOS 窗口下执行。2.2 基本程序结构下面看

10、一个最简单的 C+程序。见 FIRST.CPP2.2.1 函数函数是 C+的基本结构单元。函数可以是类的组成部分,称之为成员函数,也可以独立于类之外。函数名main 后面的圆括号是区别函数的特征。函数将遵循 C+的语法约定:圆括号被紧跟着放在函数名的后面。花括号和函数体函数的主体由一对花括号括起来,作用是包裹或界定一个程序块。每个函数都必须使用一对花括号包裹住函数体,函数体可以由多条语句组成。总以 main()函数开始在运行一个 C+程序时,第一个被执行的语句将在 main()函数的开始处。在大多数 C+程序中,main()函数通过调用各种对象的成员函数来执行程序的实际工作,另外,main()

11、函数也可以调用其他的孤立函数。具体见图 2-1 所示。2.2.2 程序语句程序语句是 C+程序设计的基本单元。具体分析 FIRST.CPP2.2.3 空白符空白符是诸如空格、回车、换行、制表符、垂直制表符和换页符的总称,这些符号对编译器来说是不可见的。可以用任意数量的空格或者制表符把几个语句放在一行,也可以把一个语句放在两行或者多行,这对编译器都没有区别。空白符对编译器不可见性有几个例外。如程序首行一般以#include 开头,这是一个必须独占一行的预处理指令;字符串常量不允许分隔成两行。2.3 使用 cout 输出语句cout不是一条程序语句,不是函数体的一部分,也没有程序语句所必需的用以结

12、束的分号,用“#”开头,是一条预处理指令。一条预处理指令也是一条给编译器的指令。编译器中有一部分被称为预处理器,负责在编译过程开始前处理这些指令。预处理器的主要作用就是把通过预处理的内建功能对一个资源进行等价替换,最常见的预处理有:文件包含,条件编译、布局控制和宏替换 4 种。 文件包含:#include 是一种最常见的预处理指令,它告诉编译器将另一个文件插入到源文件中。条件编译:#if,#ifndef,#ifdef,#endif,#undef 等是比较常见的预处理,主要是进行编译时进行有选择的挑选,注释掉一些指定的代码,以达到版本控制、防止对文件重复包含的功能。布局控制:#progma,它的

13、作用是设定编译器的状态或者是指示编译器完成一些特定的动作。#pragma 指令对每个编译器给出了一个方法,在保持与 C+语言完全兼容的情况下,给出主机或操作系统专有的特征。#pragma message(“消息文本”)宏替换: #define,它可以定义符号常量、函数功能、重新命名、字符串的拼接等各种功能。 2.4.2 头文件在例子中,预处理指令#include 告诉编译器,在编译开始前将源文件 iostream 加入到源文件中。iostream 是一个头文件,主要涉及到基本的 I/O 操作,并包含了 cout 标识符和是析取或者获取运算符,它将值从左边的流对象中取出并放到右边的变量中。2.8

14、.1 在使用的地方定义变量见 ctemp 变量。在需要使用的地方定义变量,可以使得程序清单更容易理解。但对于在函数中多次使用的变量,最好定义在函数的开始处。2.8.2 级联 #include / io 流控制头文件, 主要是一些操纵用法如:/ setw(int n),/ setprecision(int n),/ setbase(int n),/ setfill(char c)等。setw(n)用法: 通俗地讲就是预设宽度,如果要输出的字符宽度超出了 setw(n)的 n 值,就按输出字符的宽度输出。如: cout(anIntVar);见 cast.cpp强制转换只在绝对需要的时候才使用,它们

15、是一种躲避类型安全性检查的可行方法,但同时也可能会带来问题,因为它们使得编译器不能找出潜在的错误。2.14 算术运算符取余运算符 remaind.cpp算术赋值运算符 assign.cpp递增运算符 increm.cpp递减运算符2.15 库函数C+中的许多操作都是由库函数来执行的,这些函数执行文件访问、数学计算、数据转换和其他一些事情。见 sqrt.cpp许多程序并不是严格按照顺序从开始执行到结束。大多数程序根据不断变化的条件来决定做什么。取决于程序中执行所得的计算结果,控制流会从程序的一个部分转移到另一个部分。导致程序转移的语句称为控制语句,它们主要有两类:循环和选择。3.1 关系运算符关

16、系运算符用来比较两个值的大小。值的类型可以是任何 C+的内置类型,也可以是用户自定义类,比较的结果为 true 或 false。见 relat.cppC+共有六个关系运算符:等于 =不等于 !=小于 小于等于 =3.2 循环循环使得程序的一部分重复执行一定次数,只要条件满足循环就不会停止。当条件不满足时,循环结束并且将控制转移给循环后面的语句。C+中有三类循环:for 循环、while 循环和 do 循环。3.2.1 for 循环语句for 循环是最容易理解的循环,其所有的循环控制元素都集中在一个地方。for 循环将一段代码执行一个固定的次数,通常使用在当进入循环之前,就已知道循环次数的情况下

17、。见 fordemo.cppfor( init-expr; cond-expr; loop-expr )statement上述三个表达式分别是初始化表达式、条件表达式(也称测试表达式)和循环表达式(也称增量表达式) 。这三个表达式通常含有相同的变量,称之为循环变量。for 语句后面没有分号,因为 for 语句和循环体一起被认为是一个语句。初始化表达式初始化表达式仅在循环开始时执行一次,它给循环变量设置一个初始值。测试表达式通常包含一个关系运算符,循环体每次执行之前都必须执行测试表达式。测试表达式的结果决定循环体是否需要再执行一次。增量表达式增量表达式用来改变循环变量的值,总在每次循环的最后,也

18、就是循环体执行结束后再执行。多语句的循环体见 cubelist.cpp块和变量的可见性由花括号括起来的几个语句构成的循环体,称为代码块。块的一个重要意义是块内定义的变量在块外是不可见的。这种限制变量可见性的一个优点是相同的变量名可以在同一程序的不同块内重复使用。3.2.2 循环的调试过程单步调试按下 F10 键可启动调试器,启动后可以看到程序清单的左边空白处有指向 main()后大括号的黄色箭头。如果想从程序某地方而不是程序头开始,先定位光标到想开始调试的那一行代码上,然后再 Debug 菜单中选择 Start Debug中的 Run to Cursor 项,黄色箭头将出现在紧跟着所选择语句的

19、左边边框中。按下 F10 键,将使调试器步进到下一条执行语句上,黄色箭头将标明位置。如果在循环体中,可以发现黄色箭头在循环内语句间顺序向下移动,然后又跳回循环的顶端。调试函数step into(F11 键)就是单步执行,遇到子函数就进入并且继续单步执行;step over(F10 键)是在单步执行时,在函数内遇到子函数时不会进入子函数内单步执行,而是将子函数整个执行完再停止,也就是把子函数整个作为一步。 step out(Shift+F11 键)就是但单步执行到子函数内时,用 step out 就可以执行完子函数余下部分,并返回到上一层函数。如果用 F11 调试比如 cout这种库程序,追踪库

20、程序的程序清单,将会是一个冗长的过程,所以在程序调试时应该尽量避免此过程。断点断点是调试器设置的一个代码位置。当程序运行到断点时,程序中断执行,回到调试器。断点是最常用的技巧。调试时,只有设置了断点并使程序回到调试器,才能对程序进行在线调试。设置断点:可以通过下述方法设置一个断点。首先把光标移动到需要设置断点的代码行上,然后按 F9 快捷键。弹出 Breakpoints 对话框,方法是按快捷键 CTRL+B 或ALT+F9,或者通过菜单 Edit/Breakpoints 打开。打开后点击 Break at 编辑框的右侧的箭头,选择合适的位置信息。一般情况下,直接选择 line xxx 就足够了

21、,如果想设置不是当前位置的断点,可以选择 Advanced,然后填写函数、行号和可执行文件信息。去掉断点:把光标移动到给定断点所在的行,再次按 F9 就可以取消断点。同前面所述,打开 Breakpoints 对话框后,也可以按照界面提示去掉断点。条件断点:可以为断点设置一个条件,这样的断点称为条件断点。对于新加的断点,可以单击Conditions 按钮,为断点设置一个表达式。当这个表达式发生改变时,程序就被中断。底下设置包括“观察数组或者结构的元素个数”,最后一个设置可以让程序先执行多少次然后才到达断点。数据断点:数据断点只能在 Breakpoints 对话框中设置。选择“Data”页,就显示

22、了设置数据断点的对话框。在编辑框中输入一个表达式,当这个表达式的值发生变化时,数据断点就到达。一般情况下,这个表达式应该由运算符和全局变量构成,例如:在编辑框中输入 g_bFlag 这个全局变量的名字,那么当程序中有 g_bFlag= !g_bFlag 时,程序就将停在这个语句处。消息断点:VC 也支持对 Windows 消息进行截获。它有两种方式进行截获:窗口消息处理函数和特定消息中断。在 Breakpoints 对话框中选择 Messages 页,就可以设置消息断点。如果在上面那个对话框中写入消息处理函数的名字,那么每次消息被这个函数处理,断点就到达。如果在底下的下拉列表框选择一个消息,则

23、每次这种消息到达,程序就中断。观察变量WatchVC 支持查看变量、表达式和内存的值。所有这些观察都必须是在断点中断的情况下进行。观看变量的值最简单,当断点到达时,把光标移动到这个变量上,停留一会就可以看到变量的值。VC 提供一种被成为 Watch 的机制来观看变量和表达式的值。在断点状态下,在变量上单击右键,选择 Quick Watch, 就弹出一个对话框,显示这个变量的值。单击 Debug 工具条上的 Watch 按钮,就出现一个 Watch 视图(Watch1,Watch2,Watch3,Watch4),在该视图中输入变量或者表达式,就可以观察 变量或者表达式的值。注意:这个表达式不能有

24、副作用,例如+运算符绝对禁止用于这个表达式中,因为这个运算符将修改变量的值,导致软件的逻辑被破坏。Memory由于指针指向的数组,Watch 只能显示第一个元素的值。为了显示数组的后续内容,或者要显示一片内存的内容,可以使用 memory 功能。在 Debug 工具条上点 memory 按钮,就弹出一个对话框,在其中输入地址,就可以显示该地址指向的内存的内容。VariblesDebug 工具条上的 Varibles 按钮弹出一个框,显示所有当前执行上下文中可见的变量的值。特别是当前指令涉及的变量,以红色显示。寄存器Debug 工具条上的 Registers 按钮弹出一个框,显示当前的所有寄存器

25、的值。3.2.3 for 循环的变种见 factor.cppfor 语句中的变量定义循环变量定义在 for 语句中,这是 C+中一个普遍的结构,在大多数情况下它是定义循环变量的最好方法。这种在循环语句中定义的变量,仅仅在循环体中是可见的。多个初始化和增量表达式在 for 语句的初始化部分可以有不止一个表达式,但它们之间必须以逗号分隔,也可以有不止一个增量表达式,但测试表达式只能有一个。3.2.4 while 循环语句当循环次数不固定的时候,可使用 while 循环。见 endon0.cpp多语句的 while 循环体见 while4.cpp3.2.6 do 循环语句在 while 循环里,测试

26、表达式在循环的开始执行,如果进入循环时测试表达式的值为false,则循环体一次也不会执行。do 循环里,测试表达式放在循环的最后。见 divdo.cpp3.2.7 循环语句的使用规则当预先知道循环会执行多少次时,适合使用 for 循环;当不知什么时候终止循环时,应使用 while 或 do 循环。3.3 选择在程序里,一个选择将会在程序的各部分间产生一次跳转,其结果决定于表达式的值。在 C+中有几种方式可以选择,其中最重要的就是 ifelse 语句。3.3.1 if 语句见 ifdemo.cpp多语句的备选体见 if2.cpp循环内的嵌套 if 语句见 prime.cpp库函数 exit()e

27、xit 是一个库函数, exit(1)/exit(-1)表示程序异常退出 ,exit(0) 表示正常退出。 3.3.2 ifelse 语句见 ifelse.cpp库函数 getche()见 chcount.cppgetch()、getche()和 getchar()之间的区别(1) getch()和 getche()函数(例 1 例 2) 这两个函数都是从键盘上读入一个字符。其调用格式为: getch(); getche();两者的区别是: getch()函数不将读入的字符回显在显示屏幕上, 而 getche()函数却将读入的字符回显到显示屏幕上。 (2) getchar()函数(例 3 例

28、4)getchar()函数也是从键盘上读入一个字符,并带回显。它与前面两个函数的区别在于: getchar()函数等待输入直到按回车才结束,回车前的所有输入字符都会逐个显示在屏幕上。但只有第一个字符作为函数的返回值。getchar()函数的调用格式为: getchar(); getchar()被调用时,程序就等着用户按键,且将用户输入的字符依次回显到屏幕,用户必须摁完规定的次数(循环语句) (即使是回车也要摁) ,所有的字符都会保留在键盘缓存区中(回车字符也放在缓存区中) ,等待后续 getchar 调用读取。也就是说,后续的 getchar 调用不会等待用户按键,而直接读取缓冲区中的字符,直

29、到读完规定的次数后(并不是读完缓冲区的字符) ,才等待用户按键。 getcharThis is a standard function that gets a character from the stdin.getchThis is a nonstandard function that gets a character from keyboard, does not echo to screen.getcheThis is a nonstandard function that gets a character from the keyboard, echoes to screen.use

30、 getchar if you want it to work on all compilers. Use getch or getche on a system that supports it when you want keyboard input without pressing Enter.And note that the return value of all three is int! You need this to properly check for EOF.赋值表达式见 chcnt2.cpp嵌套 ifelse 语句见 adifelse.cppelse 与 if 配对见

31、badelse.cpp3.3.3 elseif 语句见 adelseif.cpp3.3.4 switch 语句见 platters.cppbreak 语句break 语句使得控制从整个 switch 语句中推出,并转移给 switch 语句之后的第一个语句。如果没有 break 语句,则控制会转移给下一个 case,直到结束。case 常量必须是一个整数或者字符常量或者是计算结果为常量的表达式。3.3.5 条件运算符3.4 逻辑运算符这类运算符允许对布尔变量进行逻辑运算。C+三个逻辑运算符int声明 rInt 是对整数的引用,初始化为引用 someInt。在这里,要求 someInt 已经有声

32、明或定义,而引用仅仅是它的别名。引用不是值,不占存储空间,声明引用时,目标的存储状态不会改变。所以,既然定义有具体分配空间的含义,那么引用只有声明,无定义。见 refe.cpp 例 1引用 rInt 用 intOne 来初始化。以后,无论改变 intOne 还是 rInt,实际上都是指 intOne。两者的值一样。 引用在声明时,必须被初始化,否则编译错误。引用运算符与地址操作符使用相同的符号。尽管彼此相关,但又不一样。(1)引用运算符放在类型名后面,只在声明的时候使用,例如:int任何其他“(2)与指针类似,下面三种声明引用的形式都是合法的:int int int (3)下面的语句包含一个引

33、用的声明和一个变量的定义:int /会误以为声明了两个引用为了提高可读性,不应在同一行上同时声明引用、指针和所有变量。如果程序寻找引用的地址,它返回目标的地址。见 refe.cpp 例 2C+没有提供访问引用本身地址的方法,因为它与指针或其他变量的地址不同,它无任何意义。指针是变量,所以可以有指针变量的引用:int* a;int* /说明 p 为整型指针的引用对 void 进行引用是不允许的。例:void /errorvoid 只是在语法上相当于一个类型,但是没有任何一个变量或对象,其类型为 void。不能建立数组的引用,例如:int a10;int /error因为数组是一个由若干个元素所组

34、成的集合,数组名表示该元素集合空间的起始地址,它自己不是一个真正的数据类型,所以无法建立一个数组的别名。引用本身是一种数据类型,所以没有引用的引用,也没有引用的指针。例如:int a;intint /error:定义一个引用的指针引用不能用类型来初始化:int /error因为引用是变量或对象的引用,而不是类型的引用。有空指针,但无空引用。int /无意义引用最重要的用途之一就是给函数传递参数。通过引用传递参数的优点是:函数可以访问请求调用的程序中的实际变量,并提供了从函数向调用它的程序返回不止一个值的机制。5.4.1 用引用传递简单的数据类型见 ref.cpp5.4.2 使用引用的更复杂的传

35、递见 reforder.cpp5.4.3 使用引用传递结构见 referst.cpp从上述几个例子可以看出:(1)传递引用给函数与传递指针的效果是一样的。这时,被调函数的形参就成为原来主调函数中的实参变量或对象的一个别名来使用,所以在被调函数中对形参变量的操作就是对其相应的目标对象(在主调函数中)的操作。(2)使用引用传递函数的参数,在内存中并没有产生实参的副本,它是直接对实参操作;而使用一般变量传递函数的参数,当发生函数调用时,需要给形参分配存储单元,形参变量是实参变量的副本;如果传递的是对象,还将调用拷贝构造函数。因此,当参数传递的数据较大时,用引用比用一般变量传递参数的效率和所占空间都好

36、。(3)使用指针作为函数的参数虽然也能达到与使用引用的效果,但是,在被调函数中同样要给形参分配存储单元,且需要重复使用“*指针变量名“ 的形式进行运算,这很容易产生错误且程序的阅读性较差;另一方面,在主调函数的调用点处,必须用变量的地址作为实参。而引用更容易使用,更清晰。5.5 重载函数重载函数的定义:在相同的声明域中的函数名是相同的,而参数表不同的,即通过函数的参数表而唯一标识并且来区分函数的一种特殊的函数。当将要定义一组函数,使它们执行一系列的操作,但是它们是应用在不同的参数类型上的。此时我们可以选择重载函数。例如: int z_x_max (int,int); /返回两个整数的最大值;i

37、nt ve_max (const vector /返回 vector 容器中的最大值;int matrix_max (const matrix /返回 matrix 引用的最大值.对于函数的用户来说,他们并不关心函数定义的细节,也就是说他们不关心判断两个整数的大小和判断数组(vector 容器)数的大小应该使用不同的函数,而对于程序的设计者来说这可是不得不想到的。程序员必须记住并查找每个函数名。 函数的重载把程序员从这种问题的复杂性中解放了出来,C+提供了这种支持。 int Max (int,int); /返回两个整数的最大值;int Max (const vector /返回 vector

38、容器中的最大值;int Max (const matrix /返回 matrix 引用的最大值; 5.5.1 不同的参数个数见 overload.cpp5.5.2 不同的参数种类见 overeng1.cpp编译器判断重载函数的第 1 步是确定该调用中所考虑的重载函数的集合,该函数集合被称为候选函数(candidant function) 。所谓候选函数就是与被调用函数同名的函数。编译器判断重载函数的第 2 步分为两动作。第一个动作是编译器从第 1 步选出的候选函数中调出可行函数(viable function)。可行函数的函数参数个数与调用的函数参数个数相同,或者可行函数的参数可以多一些,但是

39、多出来的函数参数都要有相关的缺省值;第二个动作是根据参数类型的转换规则将被调用的函数实参转换(conversion) 成候选函数的实参。转换要以候选函数为转换的目标。如果依照参数转换规则没有找到可行函数,则该调用就是错误的,则说没有函数与调用匹配,属于无匹配情况。编译器判断重载函数的第 3 步是从第 2 步中选出的可行函数中选出最佳可行函数(best match situation)。在最佳可行函数的选择中,从函数实参类型到相应可行函数参数所用的转化都要划分等级,根据等级的划分(ranked),最后选出最佳可行函数。 5.7 内联函数内联函数也称内嵌函数,它主要是解决程序的运行效率。函数调用需

40、要建立栈内存环境,进行参数传递,并产生程序执行转移,这些工作都需要一些时间开销。为了减少短函数的执行时间,可以选择将函数体中的代码直接嵌入请求调用的程序代码中。也就是说,当源文件中有函数调用时,都由插入函数的实际代码代替跳转到这个函数。重复插入相同代码会带来问题,比如破坏程序组织和失去使用函数时的清晰性。程序可能运行得更快而且占用更少空间,但是程序清单会更长和更复杂。内联函数就能解决上述问题。在源文件中,这种函数和普通的函数类似,函数以独立的实体表示,因此源文件保持很好的组织性和可读性。但是当程序编译时,无论函数调用是否发生,函数体实际上都被插入到程序中。对于很短的、只有一两条语句的函数都要考虑是否将其内联。5.8 默认参数见 missarg.cpp(1) 默认参数在函数声明中提供,当有声明又有定义时,定义中不允许默认参数。如果函数只有定义,则默认参数才可出现在函数定义中。(2) 当一个函数中有多个默认参数时,则形参分布中,默认参数应从右到左逐渐定义。在函数调用时,系统按从左到右的顺序将实参与形参结合,当实参的数目不足时,系统将按同样的顺序用声明或定义中的默认值来补齐所缺少的参数。5.10 通过引用返回见 retref.cpp

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 高等教育 > 大学课件

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报