第2章C对C的扩充.ppt

上传人:sccc 文档编号:5897006 上传时间:2023-08-31 格式:PPT 页数:109 大小:1.67MB
返回 下载 相关 举报
第2章C对C的扩充.ppt_第1页
第1页 / 共109页
第2章C对C的扩充.ppt_第2页
第2页 / 共109页
第2章C对C的扩充.ppt_第3页
第3页 / 共109页
第2章C对C的扩充.ppt_第4页
第4页 / 共109页
第2章C对C的扩充.ppt_第5页
第5页 / 共109页
点击查看更多>>
资源描述

《第2章C对C的扩充.ppt》由会员分享,可在线阅读,更多相关《第2章C对C的扩充.ppt(109页珍藏版)》请在三一办公上搜索。

1、第2章 C+对C的扩充,第2章 基本内容,掌握C+语言在结构化程序设计(非面向对象)方面对C语言扩充的性能,为编写面向对象的C+程序打下基础。,第2章 C+对C的扩充,2.1 C+的特点2.2 C+语言的文件扩展名2.3 注释符2.4 名字空间2.5 C+语言的输入输出2.6 变量的定义2.7 强制类型转换,2.8 动态内存的分配与释放2.9 作用域运算符:2.10 引用2.11 const修饰符2.12 字符串2.13 C+语言中函数的新特性习题,2.1 C+的发明人,Bjarne Stroustrup(本贾尼斯特劳斯特卢普)博士,C+语言之父,1950年出生于丹麦,1979年在英国剑桥大学

2、获得计算机科学博士学位,AT&T、贝尔实验室和ACM成员。1979年,B.S开始开发一种语言,当时称为“C with Class”,1983年演化为C+。1998年,ANSI/ISO C+标准建立,同年,B.S推出了其经典著作The C+Programming Language的第三版。Stroustrup博士是C+语言的设计者和第一位实现者,该语言业已成为世界上最通用的支持面向对象技术的程序设计语言。,Ken Thompson和Dennis Ritchie 美国科学家,1983年图灵奖获得者,UNIX和C语言的发明者。,2.1 C+开发工具的历史90年代初的Turbo C+,2.1 C+开发

3、工具的历史90年代中期的Borland C+for dos,2.1 C+开发工具的历史90年代中期的Borland C+Builder for Win,2.1 C+开发工具的历史21世纪的visual C+6.0,2.1 C+开发工具的历史visual studio 2010,2.1 C+的特点 C+语言既保留了C语言的有效性、灵活性、便于移植等全部精华和特点,又添加了面向对象编程的支持,具有强大的编程功能,可方便地构造出模拟现实问题的实体和操作;编写出的程序具有结构清晰、易于扩充等优良特性,适合于各种应用软件、系统软件的程序设计。用C+编写的程序可读性好,生成的代码质量高,运行效率仅比汇编语

4、言慢10%20%。,2.2 C+语言的文件扩展名,为了使编译器能够区别是C语言还是C+语言,C+语言体系规定用“.cpp”(意即C Plus-Plus)作为C+语言源文件的扩展名以区别于C语言用的“.C”文件扩展名。虽然仅差两个字母,但编译时的处理却相差甚远。“cpp”的文件扩展名与操作系统无关。与C+语言源文件相关的头文件扩展名一般仍用“.h”,但有些操作系统也有规定使用“.hpp”充当头文件扩展名的。,2.3 注释符,1.段注释:/*/2.单行注释:/当只做单行注释时便可用“/”符号表示从此符号起至行尾均为行注释内容。3.程序编译时将忽略所有的注释内容。,2.4 名字空间(名空间names

5、pace),名字空间域是随标准C+而引入的。它相当于一个更加灵活的文件域(全局域),可以用花括号把文件的一部分括起来,并以关键字namespace开头给它起一个名字:namespace ns1 float a,b,c;fun1(),花括号括起来的部分称声明块。声明块中可以包括:类、变量(带有初始化)、函数(带有定义)等。在域外使用域内的成员时,需加上名字空间名作为前缀,后面加上域操作符“:”。这里添加了名字空间名称的成员名被称为限定修饰名。如:ns1:a,ns1:fun1()等等。最外层的名字空间域称为全局名字空间域(global namespace scope),即文件域。名字空间域可分层嵌

6、套,同样有分层屏蔽作用。例如:namespace n1 namespace n2/名字空间嵌套 class matrix/名字空间类成员matrix 访问matrix,可写:n1:n2:matrix。,使用using声明可只写一次限定修饰名。using声明以关键字using开头,后面是被限定修饰的(qualified)名字空间成员名,例如:using n1:n2:matrix;/名字空间类成员matrix的using声明以后在程序中使用matrix时,就可以直接使用成员名,而不必使用限定修饰名。使用using指示符可以一次性地使名字空间中所有成员都可以直接被使用,比using声明方便。usin

7、g指示符以关键字using开头,后面是关键字namespace,然后是名字空间名。,标准C+库中的所有组件都是在一个被称为std的名字空间中声明和定义的。在采用标准C+的平台上使用标准C+库中的组件,只要写一个using指示符:using namespace std;就可以直接使用标准C+库中的所有成员。注意:如果使用了名空间std,则在使用#include编译预处理命令包含头文件时,必须去掉头文件的扩展名.h,否则会出错。,2.5 C+语言的输入输出,C+语言另外定义了一套流对象与运算符来替代C语言中对标准输入输出函数scanf和printf的引用。C+语言的保留字为:cout“输入内容”;

8、/cin为标准输入流对象(默认从键盘输入)#include 输入重定向,【例2.1】C+的输入输出举例。#include/使用名空间std,则必须去掉.h扩展名using namespace std;void main()char name10;int age;coutname;coutage;coutname is nameendl;coutage is ageendl;,补充(写出程序执行结果,假定输入1和2)#include/使用名空间std,则必须去掉.h扩展名using namespace std;void main()char ch1,ch2;int n1,n2;cinch1ch2

9、;n1=ch1-0;n2=n1*10+(ch2-0);coutn2;,补充(写出程序执行结果)#include/使用名空间std,则必须去掉.h扩展名#includeusing namespace std;void main()int n,count=0;for(n=1;n=100;+n)coutsetfill(*)setw(10)n;count+;if(count%5=0)coutendl;,程序执行结果,2.6 变量的定义,在C语言中,局部变量说明必须置于可执行代码段之前,不允许局部变量声明和可执行代码混合在一起。但C+在变量的定义上作了两种较大的改变,一是允许变量的定义语句可以出现在程序

10、的任何位置,使得局部变量的定义点与使用点不至于离得太远,增强程序的可读性,而且也不必在编写某一程序块的开始时就考虑要用到哪些变量;二是允许直接使用结构体名定义变量,这种扩展为程序员在编程中提供了不少方便。类似地在C+语言中联合名、枚举名也可在定义后独立地作为类型名使用。,【例2.2】C+的变量定义举例。#includeusing namespace std;void main()struct studentint no;float math;int n;cinn;student wang;wang.no=n;cinwang.math;coutwang.no wang.mathendl;,2.7

11、 强制类型转换,格式:(数据类型)(表达式)数据类型(表达式),2.8 动态内存的分配与释放,栈内存与堆内存栈空间是编译时分配的固定大小的内存。用于存放函数调用者的地址、返回值、保存的机器状态(用于返回)、函数参数、局部变量和临时变量等堆内存是程序运行时分配的大小可变的内存,也称为动态内存C+提供了两种方法进行内存动态分配和释放malloc()和free()(从C标准库中继承包含malloc.h)new和delete,2.8 动态内存的分配与释放,1.new运算符 指针变量=new 数据类型;new从堆内存中为程序分配可以保存某种类型数据的一块内存空间,并返回指向该内存的首地址,该地址存放于指

12、针变量中。堆内存可以按照要求进行分配,程序对内存的需求量随时会发生变化,有时程序在运行中可能会不再需要由new分配的内存空间,而且程序还未运行结束,这时就需要把先前占用的内存空间释放给堆内存,以后重新分配,供程序的其它部分使用。,2.delete运算符运算符delete用于释放new分配的内存空间,它的使用形式为:delete 指针变量;其中的指针变量保存着new动态分配的内存的首地址。3.注意:(1)用new获取的内存空间,必须用delete进行释放;(2)对一个指针只能调用一次delete;(3)用delete运算符作用的对象必须是用new分配的内存空间的首地址。,#include usi

13、ng namespace std;void main()int*p;p=new int;/分配内存空间*p=5;cout*p;delete p;/释放内存空间,【例2.3】new与delete应用举例。(分析运行结果),在用new分配内存的同时进行初始化。使用形式为:指针变量=new 数据类型(初始值);例如上例中的:p=new int;*p=5;也可写成:p=new int(5);,指针变量=new 数据类型数组大小;此时指针变量指向第一个数组元素的地址。使用new分配数组时,不能提供初始值。使用new建立的数组变量也由delete释放。其形式为:delete 指针变量;或delete 指针

14、变量;同样,也可以用new来为多维数组分配空间,但是除第一维可以为变量外,其它维数都必须是常量。,4用new建立数组类型的变量,注意在使用delete时,不用考虑数组的维数。有时,并不能保证一定可以从堆内存中获得所需空间,当不能成功地分配到所需要的内存时,new返回0,即空指针。因此我们可以通过判断new的返回值是否为0,来得知系统中是否有足够的空闲内存来供程序使用。例如:int*p=new int100;if(p=0)cout cant allocate more memory,terminating.endl;exit(1);其中exit函数的作用是终止程序运行。,#include usi

15、ng namespace std;void main()int n;/定义数组元素的个数 int*p;coutn;if(p=new intn)=0)cout cant allocate more memory,terminating.endl;exit(1);/分配内存空间 for(int i=0;in;i+)pi=i*2;coutNow output the array:endl;for(i=0;in;i+)coutpi;coutendl;delete p;/释放内存空间,【例2.4】从堆内存中获取一个整型数组,赋值后并打印出来。,2.9 作用域运算符:,通常情况下,如果全局变量与局部变量同

16、名,那么局部变量在其作用域内具有较高的优先权。C语言规定只能在变量的作用域内使用该变量,不能使用其他作用域中的变量,可采用C+中提供的作用域运算符:,它能指定所需要的作用域。注意:不能用:访问函数中的局部变量。在C+语言中作用域运算符:还用来限定类的成员,,#include using namespace std;float a=2.4;/全局变量void main()int a=8;/局部变量coutaendl;cout:aendl;/:a表示全局作用域中的变量a,数组程序设计举例1(要求:分析运行结果?),#include void main()int x10,i,j;j=0;/计数器初值

17、赋0 coutxi;for(i=0;i0)j+;coutj=j;,数组程序设计举例1,从键盘上输入10个整数,统计其中的正整数的个数,程序运行结果:(从键盘输入:-2 3 4-5-3 9-23 0-1 21)输出:j=4,数组程序设计举例2,用冒泡排序法对10个数按从小到大的顺序输出思想:冒泡法的基本思想是对数组元素做若干次的遍历调整,每次遍历都是对相邻的两个数两两比较并调整,将小的调到前头,大的调到后面。,第一趟循环4次,第二趟循环3次,第三趟循环2次,第四趟循环1次,5个数,数组程序设计举例2,#include void main()int a11;int i,n,t;/i表示数组下标,n

18、表示遍历次数,t用来交换数据 coutai;coutai+1)t=ai;ai=ai+1;ai+1=t;coutthe sorted numbers:endl;for(i=1;i11;i+)coutai;coutendl;,程序运行结果:input 10 numbers:1 32 13 0 23 9 45 8 19-7 the sorted numbers:-7 0 1 8 9 13 19 23 32 45,字符数组程序设计举例1(要求:分析运行结果),#include#include void main()char str20;int i,j;cin.get(str,20);j=strlen(

19、str);for(i=j-1;i=0;i-)cout.put(stri);,字符数组程序设计举例1,从键盘上输入一个字符串,然后将其逆序输出,运行的结果是:(从键盘输入:abcdefg)gfedcba,使用字符串常量来对字符数组初始化。例如char str10=student;或者直接将花括号省略,写成如下的形式char str10=student;注意:字符串常量所占的空间一定不能超过字符数组的长度。如果字符串常量占用的空间小于数组的长度,则后面的元素自动的赋值为0,字符数组,字符数组的输出,用cout输出。格式为:cout字符串或字符数组名;用cout流对象的put。格式为:cout.pu

20、t(字符或字符变量);这种方法,每次只能输出一个字符;要输出整个字符串,应采用循环的方法,#include void main()char s20=This is a string.;int i=0;while(si!=0)cout.put(si);i+;,字符数组的输出,用cout流对象的write方法。格式为:cout.write(字符串或字符数组名,个数n);其作用是输出字符数串中的前n个字符。,#include void main()char s20=This is a string.;cout.write(s,4);,分析该程序的输出结果,字符数组的输入,利用cin直接输入。格式为:

21、cin字符数组名;用这种方法输入字符串时,cin只能接收空格之前的部分。也就是说,当字符串中有空格时,用这种方法无法接收全部的字符串。利用cin流对象的getline方法。格式为:cin.getline(字符数组名,输入字符串的最大长度n);参数“字符数组名”是存放字符串的数组名称参数“输入字符串的最大长度n”包括了字符串结束标记0在内,字符串处理函数,字符串的连接函数(strcat)调用的一般形式:strcat(char,const char);,#include#include void main()char st120=qing,st2=huadaxue;strcat(st1,st2);

22、coutst1;,运行的结果:,调用的一般形式:strcpy(char,const char);例如:char s112,s2=student;strcpy(s1,s2);执行上面的语句后,s1存放的是从字符串2那里拷贝的字符串“student”和0,剩下的空间自动赋值为结束符号0。数组1的长度不能小于数组2的长度 字符串2可以为字符数组名,还可以使用一个字符串常量 不能使用赋值语句将一个字符串常量直接赋值给一个字符数组 也不能将一个字符数组直接赋值给另一个字符数组,字符串拷贝函数(strcpy),字符串比较函数(strcmp),形式:strcmp(char,const char);字符串1=

23、字符串2,返回值=0;字符串1字符串2,返回值0;字符串1字符串2,返回值0 字符串、字符串2可以是字符数组也可以是字符串常量。字符串的比较不能使用以下的形式:if(s1=s2)coutyes;只能使用该函数来进行比较。所以应该写成:if(strcmp(s1,s2)=0)coutyes;,字符数组程序设计举例(功能?),#include#include void main()char str120,str220,str350;cin.getline(str1,20);cin.getline(str2,20);if(strcmp(str1,str2)0)strcpy(str3,str1);str

24、cat(str3,str2);else strcpy(str3,str2);strcat(str3,str1);coutstr3;,字符数组程序设计举例功能,程序运行结果:(从键盘输入:China Beijing)则输出:BeijingChina,从键盘上输入两个字符串,按照由小到大的顺序将其连接在一起,二维数组,定义的一般形式为类型说明符 数组名常量表达式1常量表达式2 例:int a53;表示a为整型二维数组,其中第一维有5个下标(04),第二维有3个下标(02),数组的元素个数为15,可以用于存放5行3列的整型数据表格。,二维数组的存储,C+语言中,二维数组在内存中默认情况下采用行优先存

25、储(对float a23画存储示意图)二维数组的初始化 分行对二维数组赋初值。如 int a23=1,2,3,4,5,6;对所有数据一起赋值,放在一个花括号中。如:int a23=1,2,3,4,5,6;部分元素赋值,如:int a23=1,2,4;数组的元素全部赋值时,可以省略数组的第一维长度,二维数组元素输入输出例子,#include void main()int i,j,a23=3,0,1,10,-4,9;for(i=0;i=1;i+)for(j=0;j=2;j+)coutendlaij=aij;,程序运行结果:a00=3a01=0a02=1a10=10a11=-4a12=9,数组程序设

26、计举例3,编写程序,将一个二维数组中行和列元素互换,存到另一个二维数组中。设数组:思想:需要定义两个数组行列交换实质上是将数组元素的行列下标相互交换二维数组,必须要逐个的进行交换,所以要用到了双重循环语句,数组程序设计举例3,#include void main()int a23=1,5,9,2,6,8;int b32,i,j;coutArray a:endl;/输出原来数组的数据 for(i=0;i2;i+)for(j=0;j3;j+)coutaij;bji=aij;/将两个数组元素相互交换 coutendl;coutArray b:endl;/输出交换后的数据元素,for(i=0;i3;i

27、+)for(j=0;j2;j+)coutbij;coutendl;,程序运行结果:Array a:1 5 92 6 8Array b:1 25 69 8,综合程序设计举例,#include void main()int i,j;float a1010,sum=0,x;coutx;aij=x;for(i=0;i10;i+)sum=sum+aii+ai9-i;coutthe sum is:sumendl;,综合程序设计举例结果,一条对角线元素的下标特点是:行列下标相等。另一条对角线下标特点是:行列下标之和等于9。在每一行的每一列中找出这样的元素然后把它加到变量sum中去。,程序运行结果:input

28、 3*3 Matrix:1 3 52 4 6 7 8 9the sum is:30,思考题,从键盘输入一个字符串判断是否为“回文”比如:ABCBA,从键盘输入一个字符串判断是否为“回文”,#include#include void main()char str60;int i,j;cin.get(str,60);i=0;j=strlen(str)-1;while(stri=)i+;/寻找前面第一个不是空格的字符 while(strj=)j-;/寻找后面第一个不是空格的字符 while(ij,程序运行结果:从键盘输入:studeduts输出的结果:Yes,j从字符串的最后一个元素开始,所以初值为

29、strlen(str)-1,开始比较时,将字符串前后的空格过滤掉,2.10 引用,引用是C+语言的一个特殊的数据类型描述,用于在程序的不同部分使用两个以上的变量名指向同一地址,使得对其中任一个变量的操作实际上都是对同一地址单元进行的。在这种两个以上变量名的关系上,被声明为引用类型的变量名则是实际变量名的别名。引用运算符为&,声明引用的一般形式为:数据类型&引用变量名=变量名;或 数据类型&引用变量名=变量名;或 数据类型&引用变量名=变量名;对引用进行操作,实际上就是对被引用的变量进行操作。引用不是值,不占存储空间,声明引用时,目标的存储状态不会改变。引用一旦被初始化,就不能再重新赋值。,【例

30、2.5】引用举例。(图示变量及其引用并分析运行结果)#include void main()int num=50;int,说明:(1)在一行上声明多个引用型变量(函数)名时,要在每个变量(函数)名前都冠以“但ref=j是允许的。,(4)由于引用不是变量,所以,不能说明引用的引用,也不能说明数组元素的类型为引用数组,或指向引用的指针。例如:int/a指向变量b(5)引用与指针不同。指针的内容或值是某一变量的内存单元地址,而引用则与初始化它的变量具有相同的内存单元地址。指针是个变量,可以把它再赋值成其它的地址,然而,建立引用时必须进行初始化并且决不会再指向其它不同的变量。,地址,(6)要注意区分引

31、用运算符和地址运算符的区别。例如:int num=50;int/num被修改为100其中ref2也是对num的引用。,(8)可以把函数的参数说明成引用以建立函数参数的引用传递方式好处:C+的引用传递方式的实参和形参指向同一内存地址,减少值传递引起的数据堆栈复制避免地址传递引起的地址溢出错误C+提供引用的主要用途就是建立函数参数的引用传递方式C语言的函数参数传递只能采用值传递和地址传递三种传递方式比较的例子交换两个数,用一般变量作为参数交换两个数采用传值方式#include void swap(int x,int y)int t;t=x;x=y;y=t;void main()int a=1,b=

32、2;cout交换前,a=a,b=bendl;swap(a,b);cout交换后,a=a,b=bendl;,运行结果:交换前,a=1,b=2交换后,a=1,b=2,交换功能未实现。说明采用传值方式时,实参不受影响,用指针变量作为参数交换两个数采用传址方式#include void swap(int*x,int*y)int t;t=*x;*x=*y;*y=t;void main()int a=1,b=2;cout交换前,a=a,b=bendl;swap(,运行结果:交换前,a=1,b=2交换后,a=2,b=1,采用传地址方式传递参数。在函数中改变了形参,就是改变了实参,因为他们是指向同一地址的指针

33、变量。因此交换功能实现,用引用作为参数交换两个数采用传引用方式#include void swap(int,运行结果:交换前,a=1,b=2交换后,a=2,b=1,采用传引用方式传递参数。函数中的形参是主调函数中实参的引用。在函数中改变了形参,就是改变了实参,因为他们指向同一地址。因此交换功能实现,地址传递和引用传递的比较。引用作为参数,主调函数可直接使用变量名地址作为参数,主调函数要将变量地址传递过去引用作为参数,函数可对形参变量直接操作地址作为参数,函数需通过指针对地址间接操作,(9)有空指针,无空引用(10)引用不能用数据类型来初始化。如:int&ref=int;/error(11)函数

34、调用可以作为左值(函数返回值为引用类型)引用表达式是一个左值表达式,因此它可以出现在形、实参数的任何一方。若一个函数返回了引用,那么该函数的调用也可以被赋值。一般说,当返回值不是本函数内定义的局部变量时就可以返回一个引用。在通常情况下,引用返回值只用在需对函数的调用重新赋值的场合,也就是对函数的返回值重新赋值的时候。避免将局部作用域中变量的地址返回,就使函数调用表达式作为左值来使用。函数返回值为引用类型表示该函数返回值是一个变量的别名,故可将函数调用作为一个变量使用而进行赋值,【例2.8】统计学生中A类学生与B类学生各为多少个。A类学生的标准是平均分在80分以上,其余都是B类学生。,【补充例子

35、】,#include int,【补充例子】,#include int,(12)定义返回引用的函数时,注意不要返回对该函数内局部变量的引用。为什么?,因为局部变量的生存期局限于函数内部,函数返回时局部变量消失,导致函数返回一个无效的引用。故函数返回的引用是对某一个函数参数的引用且这个参数本身也是引用类型,【例2.9】返回的局部作用域内的变量,函数作为左值。,2.11 const修饰符,#define PI 3.1415926const float PI=3.1415926;这个常量是有类型的,它有地址,可以用指针指向这个值,但不能修改它。C+建议用const取代#define定义常量。,注意:,

36、(1)使用const修饰符定义常量时,必须初始化;(2)常量一旦被定义,在程序中任何地方都不能 再更改。(3)如果用const定义的是一个整型常量,int可以省略。(4)与#define定义的常量有所不同,const定义的常量可以有自己的数据类型,这样C+编译程序可以进行更加严格的类型检查,具有良好的编译时的检测性。,(5)函数参数也可以用const说明,用于保证实参在该函数内部不被改动,大多数C+编译器能对具有const参数的函数进行更好的代码优化。例如,通过函数max求出整型数组a100中的最大值,函数原型应该是:int max(const int*pa);这样做的目的是确保原数组的数据不

37、被破坏,即在函数中对数组元素的操作只许读,不许写。,const与指针一起使用的组合情况:,(1)指向常量的指针 指向常量的指针是指一个指向常量的指针变量。const char*pc=abcd;声明指向常量的指针变量pc,它指向一个字符串常量由于使用了const,不允许改变指针所指的常量,因此以下语句是错误的:pc3=x;但是由于pc是一个指向常量的普通指针变量,不是常指针,因此可以改变pc的值。例如以下语句是允许的:pc=jkkk;,const与指针一起使用的组合情况:,(2)常指针常指针是指指针本身,而不是它指向的对象声明为常量。例如:char*const pc=abcd;/常指针这个语句的

38、含义为:声明一个名为pc的指针变量,该指针是指向字符型数据的常指针,用“abcd”的地址初始化该常指针。创建一个常指针,就是创建不能移动的固定指针,但是它所指的数据可以改变。例如:pc3=x;/合法pc=dfasdfa;/不合法,const与指针一起使用的组合情况:,(3)指向常量的常指针整个指针本身不能改变,它所指向的值也不能改变。要声明一个指向常量的常指针,二者都要声明为const。例如:const char*const pc=abcd;/指向常量的常指针这个语句的含义为:声明一个名为pc的指针变量,它是一个指向字符型常量的常指针,用“abcd”的地址初始化该指针。以下两个语句都是错误的:

39、pc3=x;/错误,不能改变指针所指的值pc=dfasdfa;/错误,不能改变指针本身,2.12 字符串,除了计算外,文本处理也是编程过程中一个非常重要的方面。在C语言中使用字符数组和字符指针实现字符串,但是在C+中提供了一种既方便又好用的string类型。下面通过一个简单的例子说明string类型的使用。【例2.10】字符串类string的使用。,【例2.10】,#include#include/使用字符串string类型的程序应包含头文件using namespace std;void main()string s,t;couts;/由键盘输入一行文本,并把它赋给sring类型的变量s,注

40、意:/使用此方式输入的字符串中不能包含空白字符,具体请参见7.1.2小节t=I like programming!;cout字符串的输出:endlsendltendl;couts.append(OK!)endl;/append为string类的成员函数,2.13 C+语言中函数的新特性,2.13.1 函数原型(Function Prototype)2.13.2 内联(inline)函数2.13.3 带缺省参数的函数2.13.4 函数重载(overload)2.13.5 函数模板(function template),C+要求为每一个函数建立原型,用以说明函数的名称、参数个数及类型和函数返回值的

41、类型。其主要目的是让C+编译程序进行类型检查,即形参与实参的类型匹配检查,以及返回值是否与原型相符,以维护程序的正确性。所以应养成将声明与定义分别编写的编程习惯。函数原型与函数的定义要在函数的返回类型,函数名和参数的类型及数量这三条线上保持一致。C+中函数要经过三个阶段:先声明,再定义,后使用。,2.13.1 函数原型(Function Prototype),求44方阵中所有元素中的最大值,#include int max_element(int array44);/函数声明void main()int p44=1,22,3,4,3,4,6,18,6,5,2,9,0,6,1,34;coutma

42、x)max=arrayij;return(max);,程序说明,无论是一维数组名还是二维数组名作函数参数,传送的都是地址。二维数组名作函数参数时,在被调用函数中对形参数组定义时可以指定每一维的大小,也可以省略第一维的大小说明。如int array4与int array44都是合法的。形参数组的类型应与实参数组相同,它们必须是具有相同长度的一维数组所组成。不能只指定第一维而省略第二维,如int array4的写法是错误的。在第二维大小相同的前提下,形参数组的第一维可以与实参数组不同。如实参数组定义为:int score44;而形参数组定义为:int array14;或int array94;均可

43、以。,2.13.2内联(inline)函数,在执行程序过程中如果要进行函数调用,则系统要将程序当前的一些状态信息存到栈中,同时转到函数的代码处去执行函数体语句,这些参数保存与传递的过程中需要时间和空间的开销,使得程序执行效率降低,特别是在程序频繁地进行函数调用以及函数代码段比较少时,这个问题会变得更为严重。为了解决这个问题,C+引入了内联函数机制(inline function)。(画图举例)使用内联函数是一种用空间换时间的措施,通过将函数体的代码直接插入到函数调用处来节省调用函数的时间开销。,2.13.2内联(inline)函数,使用内联函数是一种用空间换时间的措施,若内联函数较长,且调用太

44、频繁时,程序将加长很多。因此,通常只有较短的函数才定义为内联函数,对于较长的函数最好作为一般函数处理。,一般情况下,我们对内联函数做如下的限制:(1)不能有递归(2)不能包含静态数据(3)不能包含循环(4)不能包含switch和goto语句(5)不能包含数组 若一个内联函数定义不满足以上限制,则编译系统把它当作普通函数对待。【例2.11】内联函数的使用。,2.13.3带缺省参数的函数,如果在函数说明或函数定义中为形参指定一个缺省值,则称此函数为带缺省参数的函数。有对应的实参,则用实参的值,否则用形参的缺省值。当函数调用发生后,在形参表中等号后的各“缺省值”将起实参的传递作用。如果函数有多个缺省

45、参数,则缺省参数必须是从右向左定义,并且在一个缺省参数的右边不能有未指定缺省值的参数。void fun(int a=3,int b=6,int c,int d);void fun(int a=65,int b=3,int c,int d=3);需要特别注意的是如果在函数原型的声明中设置了函数参数的缺省值,则不可再在函数定义的头部重复设置,否则编译时将出现错误信息。,求3个正整数中的最大数(分析运行结果),#include void main()int max(int a,int b,int c=0);/*能否移到main外面*/int a,b,c;cinabc;couta)a=b;if(ca)

46、a=c;return a;,运行结果:19 2 56max(a,b,c)=max(a,b)=,2.13.4函数重载(overload),C+编译系统允许为两个或两个以上的函数取相同的函数名,但是形参的个数或者形参的类型不应相同,编译系统会根据实参和形参的类型及个数的最佳匹配,自动确定调用哪一个函数,这就是所谓的函数重载。C+允许用一个函数名定义多个函数,这些函数的参数个数和参数类型不同,称为重载函数。即对一个函数名重新赋予新的含义,使一个函数名可以多用函数重载无需特别声明,只要所定义的函数与已经定义的同名函数形参形式不完全相同,C+编译器就认为是函数的重载。【例2.12】重载函数应用举例,#i

47、nclude int max(int x,int y)int z;z=(xy?x:y);return z;float max(float x,float y)float z;z=(xy?x:y);return z;void main()int num1,num2;float num3,num4;cinnum1num2num3num4;coutmax(num1,num2)=max(num1,num2)endl;coutmax(num3,num4)=max(num3,num4)endl;,在使用重载函数时要注意:,不可以定义两个具有相同名称、相同参数类型和相同参数个数,只是函数返回值不同的函数。i

48、nt func(int x);float func(int x);如果某个函数参数有缺省值,必须保证其参数缺省后调用形式不与其它函数混淆。int f(int a,float b);void f(int a,float b,int c=0);函数调用语句:f(10,2.0);具有二义性,既可以调用第一个函数,也可以调用第二个函数,编译器不能根据参数的形式确定到底调用哪一个。,使用函数重载的条件,函数名相同,函数的返回值类型可以不同,但各函数的参数表中,参数个数,类型或顺序应有所不同类型名 func(double,int);类型名 func(int,double);/函数形参顺序不同类型名 fun

49、c(int);/函数形参数目不同类型名 func(double,double);/函数形参类型不同这样就形成了函数的重载,2.13.5函数模板(function template),C+语言中可以使用模板来避免在程序中多次书写相同的代码。所谓模板是一种使用无类型参数来产生一系列函数或类的机制,模板是以一种完全通用的方法来设计函数和类,而不必预先说明将被使用的每个对象的数据类型。通过模板可以产生类或函数的集合,使它们操作不同的数据类型,从而避免为每一种数据类型产生一个单独的类或函数。模板分为函数模板和类模板。C+提供函数模板,可以进一步提高程序代码的可重复利用程度。只要实现一个函数模板就可以用这

50、个模板生成许多具体的函数(模板的实例化)模板函数,1.函数模板,函数模板的一般说明形式如下:template(模板函数形参表)/函数定义体尖括号中不能为空,参数可以有多个,用逗号分开。模板参数主要是模板类型参数。模板类型参数(template type parameter)代表一种类型,由关键字 class 或 typename后加一个标识符构成,在这里两个关键字的意义相同,它们表示后面的参数名代表一个基本数据类型或用户定义的类型。,如果类型形参多于一个,则每个类型形参都要使用class或typename。中的参数必须是唯一的,而且中至少出现一次。如:template,则“T”可以在程序运行时

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

当前位置:首页 > 建筑/施工/环境 > 农业报告


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号