版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、14.1c+的特点的特点14.2最简单的最简单的c+程序程序14.3c+的输入输出的输入输出14.4函数的重载函数的重载14.5带缺省参数的函数带缺省参数的函数14.6变量的引用类型变量的引用类型514.7内置函数内置函数14.8作用域运算符作用域运算符14.9动态分配动态分配/撤销内存的运算符撤销内存的运算符new和和delete14.10小结小结第第1414章章 c+c+对对c c的扩充的扩充14.1 c+的特点的特点 c语言是结构化和模块化的语言,它是面向过程的。语言是结构化和模块化的语言,它是面向过程的。在处理较小规模的程序时,程序员用在处理较小规模的程序时,程序员用c语言较得心语言较
2、得心应手。但是当问题比较复杂、程序的规模比较大应手。但是当问题比较复杂、程序的规模比较大时,结构化程序设计方法就显出它的不足。时,结构化程序设计方法就显出它的不足。c程序程序的设计者必须细致地设计程序中的每一个细节,的设计者必须细致地设计程序中的每一个细节,准确地考虑到程序运行时每一时刻发生的事情,准确地考虑到程序运行时每一时刻发生的事情,例如各个变量的值是如何变化的,什么时候应该例如各个变量的值是如何变化的,什么时候应该进行哪些输入,在屏幕上应该输出什么等。这对进行哪些输入,在屏幕上应该输出什么等。这对程序员的要求是比较高的,如果面对的是一个复程序员的要求是比较高的,如果面对的是一个复杂问题
3、,程序员往往感到力不从心。当初提出结杂问题,程序员往往感到力不从心。当初提出结构化程序设计方法的目的是解决软件设计危机,构化程序设计方法的目的是解决软件设计危机,但是这个目标并未完全实现。但是这个目标并未完全实现。 为了解决软件设计危机,在为了解决软件设计危机,在20世纪世纪80年代提出了年代提出了面向对象的程序设计面向对象的程序设计(object-oriented programming,简称,简称oop) ,在这种形势下,在这种形势下,c+应运而生。应运而生。c+是由贝尔实验室的是由贝尔实验室的bjarne stroustrup博士及其同事在博士及其同事在c语言的基础上开发成语言的基础上开
4、发成功的。功的。c+保留了保留了c语言原有的所有优点,增加了语言原有的所有优点,增加了面向对象的机制。面向对象的机制。c+与与c完全兼容,用完全兼容,用c语言写语言写的程序可以不加修改地用于的程序可以不加修改地用于c+。从。从c+名字可以名字可以看出它是对看出它是对c的扩充,是的扩充,是c的超集。它既可以用于的超集。它既可以用于结构化程序设计,又可用于面向对象的程序设计,结构化程序设计,又可用于面向对象的程序设计,因此它是一个功能强大的混合型的程序设计语言。因此它是一个功能强大的混合型的程序设计语言。 使用使用c+必须事先安装必须事先安装c+编译系统,在编译系统,在dos系统系统下可以使用下可
5、以使用turbo c+或或borland c+。c源程序源程序的后缀一般为的后缀一般为.c,而,而c+的后缀一般为的后缀一般为.cpp(为(为c plus plus的缩写,即的缩写,即c+)。在)。在borland c+开发开发环境中,既可以使用环境中,既可以使用c语言,也可以使用语言,也可以使用c+语言。语言。它有两个编译系统,根据源程序文件名的后缀是它有两个编译系统,根据源程序文件名的后缀是.c还是还是.cpp来决定使用哪个编译系统。来决定使用哪个编译系统。 如上所述,面向对象程序设计方法主要是解决大如上所述,面向对象程序设计方法主要是解决大型软件的设计问题。只有编写过大型程序的人才型软件
6、的设计问题。只有编写过大型程序的人才会体会到会体会到c的不足和的不足和c+的优点。的优点。c+是一种大型是一种大型语言,其功能、概念和语法规定都比较复杂,要语言,其功能、概念和语法规定都比较复杂,要深入掌握它需要花较多的时间,尤其是需要有较深入掌握它需要花较多的时间,尤其是需要有较丰富的实践经验。用丰富的实践经验。用c+编程的主要是软件专业人编程的主要是软件专业人员。学校里一般专业的程序设计课程任务主要是员。学校里一般专业的程序设计课程任务主要是进行程序设计的基本训练,因此,我们认为当前进行程序设计的基本训练,因此,我们认为当前对大多数学生来说,应先掌握好对大多数学生来说,应先掌握好c语言程序
7、设计。语言程序设计。有了有了c语言的基础在需要时再学习语言的基础在需要时再学习c+不会太困难。不会太困难。为了使读者对为了使读者对c+有初步的了解,以便为今后学习有初步的了解,以便为今后学习c+打下基础,我们在进行本书的修订时特地增加打下基础,我们在进行本书的修订时特地增加了第了第14章和第章和第15章,介绍章,介绍c+的初步知识。的初步知识。 c+对对c的的“增强增强”,表现在两个方面:,表现在两个方面: (1) 在原来面向过程的机制基础上,对在原来面向过程的机制基础上,对c语言的功语言的功能做了不少扩充。能做了不少扩充。 (2) 增加了面向对象的机制。增加了面向对象的机制。 本章介绍本章介
8、绍c+对对c功能的扩充。第功能的扩充。第15章介绍有关面章介绍有关面向对象的内容。向对象的内容。14.2 最简单的最简单的c+程序程序 例例14.1 输出一行字符。输出一行字符。#include #include /* 本程序的作用是输出一行字符本程序的作用是输出一行字符 */void main( ) printf(this is a c+ program. n); cout this is a c+ program. n ; /本行输出一行字符本行输出一行字符 本程序和以前见过的本程序和以前见过的c程序有什么不同?程序有什么不同? (1) 在在c+程序中一般习惯在主函数程序中一般习惯在主函数
9、main前面加了前面加了一个类型声明符一个类型声明符void,表示,表示main函数没有返回值。函数没有返回值。 (2) 除了可以用除了可以用 /*/ 形式的注释行外,还允许形式的注释行外,还允许使用以使用以/ 开头的注释。从程序最后一行中可以看到:开头的注释。从程序最后一行中可以看到:以以/开头的注释可以不单独占一行,它出现在语句开头的注释可以不单独占一行,它出现在语句之后。编译系统将之后。编译系统将/ 以后到本行末尾的所有字符都以后到本行末尾的所有字符都作为注释。应注意:它是单行注释,不能跨行。作为注释。应注意:它是单行注释,不能跨行。c+的程序设计人员多愿意用这种注释方式,它比的程序设计
10、人员多愿意用这种注释方式,它比较灵活方便。较灵活方便。 (3) 除了可以用除了可以用printf函数输出信息外,还可以用函数输出信息外,还可以用cout进行输出。进行输出。cout要与运算符要与运算符配合使用,程序配合使用,程序中中cout的作用是将的作用是将运算符右侧的内容送到输出运算符右侧的内容送到输出设备中输出。设备中输出。 (4) 使用使用cout需要用到头文件需要用到头文件iostream.h,在程序的,在程序的第一行用第一行用#include命令将该头文件命令将该头文件“包含包含”进来。进来。 程序运行时输出:程序运行时输出:this is a c+ program. this i
11、s a c+ program.可以看到程序中最后两个语可以看到程序中最后两个语句的作用相同,都是输出句的作用相同,都是输出this is a c+ program.。14.3 c+的输入输出的输入输出 在在c语言中文件不是由记录构成的。对文件的存取语言中文件不是由记录构成的。对文件的存取是以字节为单位的,对一个是以字节为单位的,对一个c文件的输入和输出是文件的输入和输出是一个字节流。输入和输出的数据流的开始和结束一个字节流。输入和输出的数据流的开始和结束只受程序控制而不受物理符号(如回车换行符)只受程序控制而不受物理符号(如回车换行符)的控制。这种文件称为流式文件。在输入操作中,的控制。这种文
12、件称为流式文件。在输入操作中,字节从输入设备流向内存,在输出操作中,字节字节从输入设备流向内存,在输出操作中,字节从内存流向输出设备。从内存流向输出设备。c+为了方便使用,除了可为了方便使用,除了可以利用以利用printf和和scanf函数进行输出和输入外,还增函数进行输出和输入外,还增加了标准输入输出流加了标准输入输出流cout和和cin。cout是由是由c和和out两两个单词组成的,代表个单词组成的,代表c+的输出流,的输出流,cin是由是由c和和in两个单词组成的,代表两个单词组成的,代表c+的输入流。它们是在头的输入流。它们是在头文件文件iostream.h中定义的。在键盘和显示器上的
13、输中定义的。在键盘和显示器上的输入输出称为标准输入输出,标准流是不需要打开入输出称为标准输入输出,标准流是不需要打开和关闭文件即可直接操作的流式文件。和关闭文件即可直接操作的流式文件。 c+预定义的标准流如表预定义的标准流如表14.1所示。所示。表表14.1流名流名含义含义 隐含设备隐含设备cin标准输入标准输入 键盘键盘cout 标准输出标准输出 屏幕屏幕cerr标准出错输出标准出错输出 屏幕屏幕clogcerr的缓冲形式的缓冲形式 屏幕屏幕14.3.1 用用cout进行输出进行输出 cout必须和输出运算符必须和输出运算符一起使用。一起使用。 在这里不在这里不作为位运算的左移运算符,而是起
14、插入的作用,作为位运算的左移运算符,而是起插入的作用,例如:例如:couthello!n;的作用是将字符串的作用是将字符串“hello!n” 插入到输出流插入到输出流cout中,也就是输出在中,也就是输出在标准输出设备上。标准输出设备上。 也可以不用也可以不用n控制换行,在头文件控制换行,在头文件iostream.h中定中定义了控制符义了控制符endl代表回车换行操作,作用与代表回车换行操作,作用与n相同。相同。endl的含义是的含义是end of line,表示结束一行。,表示结束一行。 可以在一个输出语句中使用多个运算符可以在一个输出语句中使用多个运算符 将多个将多个输出项插入到输出流输出
15、项插入到输出流cout中,中,运算符的结合方运算符的结合方向为自左向右,因此各输出项按自左向右顺序插向为自左向右,因此各输出项按自左向右顺序插入到输出流中。例如:入到输出流中。例如:for (i=1; i=3;i+)coutcount=iendl; 输出结果为输出结果为:count=1count=2count= 3 注意:每输出一项要用一个注意:每输出一项要用一个 符号。不能写成符号。不能写成 couta,b,c,a; 形式。形式。 用用cout和和 可以输出任何类型的数据,如:可以输出任何类型的数据,如:float a=3.45;int b=5;char c=a;couta=a,b=b,c=
16、cendl; 输出结果为输出结果为a=3.45,b=5,c=a 可以看到在输出时并未指定数据的类型(如实型、可以看到在输出时并未指定数据的类型(如实型、整型),系统会自动按数据的类型进行输出。这整型),系统会自动按数据的类型进行输出。这比用比用printf函数方便,在函数方便,在printf函数中要指定输出函数中要指定输出格式符(如格式符(如%d,%f,%c等)。等)。 如果要指定输出所占的列数,可以用控制符如果要指定输出所占的列数,可以用控制符setw设设置置(注意:若使用注意:若使用setw,必须包含头文件必须包含头文件 iomanip.h),如如setw(5) 的作用是为其后面一个输出项
17、预留的作用是为其后面一个输出项预留5列,列,如输出项的长度不足如输出项的长度不足5列则数据向右对齐,若超过列则数据向右对齐,若超过5列则按实际长度输出。如将上面的输出语句改为:列则按实际长度输出。如将上面的输出语句改为:couta=setw(6)aendlb=setw(6)bendlc=setw(6)cendl; 输出结果为输出结果为a=3.45b=5c=a 在在c+中将数据送到输出流称为中将数据送到输出流称为“插插入入”(inserting) ,或,或“放到放到”(putting) 。 运算符运算符从输入设备键盘取得数据送到输入流从输入设备键盘取得数据送到输入流cin中,然后送到中,然后送到
18、内存。在内存。在c+中,这种输入操作称为中,这种输入操作称为“提提取取”(extracting) 或或“得到得到”(getting) 。 常称为常称为“提提取运算符取运算符”。 cin要与要与 配合使用。例如:配合使用。例如:int a;float b;cinab; /输入一个整数和一个实数。注意不要写成输入一个整数和一个实数。注意不要写成cina,b; 可以从键盘输入可以从键盘输入:20 32.45 (数据间以空格分隔)(数据间以空格分隔) a和和b分别获得值分别获得值20和和32.45。用。用cin和和 输入数据输入数据同样不需要在本语句中指定数据类型(用同样不需要在本语句中指定数据类型(
19、用scanf函函数输入时要根据数据类型指定输入格式符,如数输入时要根据数据类型指定输入格式符,如%d,%c等)。等)。 例例14.2 cin与与cout一起使用。一起使用。#include void main( )coutplease enter your name and age:name; cinage; coutyour name is nameendl; coutyour age is ageendl; 运行情况如下:运行情况如下:please enter your name and age:wang-li 19 your name is wang-liyour age is 19 程
20、序中对变量的定义放在执行语句之后。程序中对变量的定义放在执行语句之后。c语言是语言是不允许这样的,它要求声明部分必须在执行语句不允许这样的,它要求声明部分必须在执行语句之前。而之前。而c+允许对变量的声明放在程序的任何位允许对变量的声明放在程序的任何位置(但必须在使用该变量之前)。这是置(但必须在使用该变量之前)。这是c+对对c限限制的放宽。制的放宽。 c+为流输入输出提供了格式控制,如:为流输入输出提供了格式控制,如:dec(用十用十进制形式),进制形式),hex(用十六进制形式),用十六进制形式),oct(用八进用八进制形式),制形式), 还可以控制实数的输出精度等。还可以控制实数的输出精
21、度等。14.4 函函 数数 的的 重重 载载 在上一节用到了插入运算符在上一节用到了插入运算符。 这两个运算符本来是左移运算符和右移运算符,这两个运算符本来是左移运算符和右移运算符,现在把它作为输入输出运算符。即允许一个运算现在把它作为输入输出运算符。即允许一个运算符用于不同场合,有不同的含义,这就叫运算符符用于不同场合,有不同的含义,这就叫运算符的的“重载重载”(overloading),即重新赋予它新的含义。,即重新赋予它新的含义。其实就是其实就是“一物多用一物多用”。 函数也可以重载。用函数也可以重载。用c语言编程时,有时会发现有语言编程时,有时会发现有几个不同名的函数,实现的是同一类的
22、操作。例几个不同名的函数,实现的是同一类的操作。例如要求从如要求从3个数中找出其中最大者,而这个数中找出其中最大者,而这3个数的个数的类型事先不确定,可以是整数、实数或长整数。类型事先不确定,可以是整数、实数或长整数。程序设计者必须分别设计出程序设计者必须分别设计出3个函数,其原型为:个函数,其原型为: int max1(int a, int b, int c); (求(求3个整数中的最大者)个整数中的最大者) float max2(float a, float b, float c); (求(求3个实数中的最大者)个实数中的最大者) long max3(long a, long b, lon
23、g c); (求(求3个长整数中的最大者)个长整数中的最大者) c语言规定在同一作用域(如同一文件模块中)中语言规定在同一作用域(如同一文件模块中)中不能有同名的函数,因此不能有同名的函数,因此3个函数的名字不相同。个函数的名字不相同。 c+允许在同一作用域中用同一函数名定义多个函允许在同一作用域中用同一函数名定义多个函数,这些函数的参数个数和参数类型不同。这就数,这些函数的参数个数和参数类型不同。这就是函数的重载,即一个函数名多用。是函数的重载,即一个函数名多用。 对上面的问题可以编写如下的对上面的问题可以编写如下的c+程序。程序。 例例14.3 求求3个数中最大的数(分别考虑整数、实数、个
24、数中最大的数(分别考虑整数、实数、长整数的情况)。长整数的情况)。#include int max(int a, int b, int c) /求求3个整数中的最大者个整数中的最大者 if (ba) a=b; if (ca) a=c; return a; float max(float a,float b, float c) /求求3个实数中的最大者个实数中的最大者 if (ba) a=b; if (ca) a=c; return a; long max(long a,long b,long c) /求求3个长整数中的最大者个长整数中的最大者 if (ba) a=b; if (ca) a=c;
25、 return a; void main( )int a,b,c; float d,e,f; long g,h,i; cinabc; cindef; cinghi; int m; m= max(a,b,c); /函数值为整型函数值为整型 cout max-i=mendl; float n; n=max(d,e,f); /函数值为实型函数值为实型 coutmax-f=nendl; long int p; p=max(g,h,i); /函数值为长整型函数值为长整型 coutmax-l=pendl; 运行情况如下:运行情况如下:85-6 56.990.76543.1 67543-56778123 m
26、ax-i=8 (3个整数的最大值)个整数的最大值)max-f=90.765 (3个实数的最大值)个实数的最大值)max-l=78123 (3个长整数的最大值)个长整数的最大值) main函数函数3次调用次调用max函数,每次实参的类型不同。函数,每次实参的类型不同。系统会根据实参的类型找到与之匹配的函数,然系统会根据实参的类型找到与之匹配的函数,然后调用该函数。后调用该函数。 上例上例3个个max函数的参数个数相同而类型不同。参函数的参数个数相同而类型不同。参数个数也可以不同,见下例。数个数也可以不同,见下例。 例例14.4求求n个整数中的最大数。个整数中的最大数。n的值为的值为2和和3。#i
27、nclude int max(int a, int b, int c) /求求3个整数中的最大者个整数中的最大者 if (ba) a=b; if (ca) a=c; return a; int max(int a, int b) /求两个整数中的最大者求两个整数中的最大者 if (ab) return a; else return b;void main( )int a=7,b=-4,c=9;coutmax(a,b,c)endl; /输出输出3个整数中的最大者个整数中的最大者coutmax(a,b)endl; /输出两个整数中的最大者输出两个整数中的最大者 运行情况如下:运行情况如下:97 两
28、次调用两次调用max函数的参数个数不同,系统会根据参函数的参数个数不同,系统会根据参数的个数找到与之匹配的函数并调用它。数的个数找到与之匹配的函数并调用它。 参数的个数和类型可以都不同。应当注意:重载参数的个数和类型可以都不同。应当注意:重载函数的参数个数或类型必须至少有一者不同,函函数的参数个数或类型必须至少有一者不同,函数返回值类型可以相同也可以不同。但不允许参数返回值类型可以相同也可以不同。但不允许参数个数和类型都相同而只有返回值类型不同,因数个数和类型都相同而只有返回值类型不同,因为系统无法从函数的调用形式上判断哪一个函数为系统无法从函数的调用形式上判断哪一个函数与之匹配。与之匹配。1
29、4.5 带缺省参数的函数带缺省参数的函数 一般情况下,实参个数应与形参个数相同。一般情况下,实参个数应与形参个数相同。c+允允许实参个数与形参个数不同。办法是在形参表列许实参个数与形参个数不同。办法是在形参表列中对一个或几个形参指定缺省值中对一个或几个形参指定缺省值(或称默认值或称默认值)。例。例如某一函数的首部可用如下形式:如某一函数的首部可用如下形式:void fun(int a, int b, int c=100) 在调用此函数时如写成在调用此函数时如写成fun(2,4,6),则形参,则形参a,b,c的值分别为的值分别为2,4,6(这是与过去一样的)。如(这是与过去一样的)。如果写成果写
30、成fun(2,4) ,即少写了最后一个参数,由于,即少写了最后一个参数,由于在函数定义时已指定了在函数定义时已指定了c的缺省值为的缺省值为100,因此,因此a,b,c的值分别为的值分别为2,4,100。请注意:赋予缺省值。请注意:赋予缺省值的参数必须放在形参表列中的最右端。例如:的参数必须放在形参表列中的最右端。例如:void f1(float a, int b, int c=0, char d=a) (正确正确)void f2(float a, int c=0, char d=a, int b) (不正确不正确) 利用这一特性,可以使函数的使用更加灵活。例利用这一特性,可以使函数的使用更加灵
31、活。例如例如例14.4求两个数或求两个数或3个数中的最大数。也可以不个数中的最大数。也可以不用重载函数,而将函数用重载函数,而将函数max的首行写成的首行写成int max(int a, int b, int c=-32768) 如果只想从两个数中找大者,则可以在调用时写如果只想从两个数中找大者,则可以在调用时写成成max(100,675) ,c的值自动取的值自动取-32768,由于,由于-32768是最小整数,因此从是最小整数,因此从100, 675, -32768中选中选大者和从大者和从100, 675中选大者的结果是一样的。中选大者的结果是一样的。 注意:不要同时使用重载函数和缺省参数的
32、函数,注意:不要同时使用重载函数和缺省参数的函数,因为当调用函数时少写一个参数,系统无法判定因为当调用函数时少写一个参数,系统无法判定是利用重载函数还是利用缺省参数的函数,会发是利用重载函数还是利用缺省参数的函数,会发生错误。生错误。14.6 变量的引用类型变量的引用类型14.6.1 引用的概念引用的概念 “引用引用”(reference)是是c+的一种新的变量类型,的一种新的变量类型,是对是对c的一个重要扩充。它的作用是为一个变量起的一个重要扩充。它的作用是为一个变量起一个别名。假如有一个变量一个别名。假如有一个变量a,想给它起一个别名,想给它起一个别名b,可以这样写:,可以这样写:int
33、a;int &b=a; 这就声明了这就声明了b是是a的的“引用引用”,即,即a的别名。经过这的别名。经过这样的声明后,使用样的声明后,使用a或或b的作用相同,都代表同一的作用相同,都代表同一变量。注意:在上述声明中,变量。注意:在上述声明中,&是是“引用声明符引用声明符”, 并不代表地址。不要理解为并不代表地址。不要理解为“把把a的值赋给的值赋给b的地的地址址”。 声明引用并不另开辟内存单元,声明引用并不另开辟内存单元,b和和a都代表同一都代表同一变量单元。在声明一个引用型变量时,必须同时变量单元。在声明一个引用型变量时,必须同时使之初始化,即声明它代表哪一个变量。使之初始化,
34、即声明它代表哪一个变量。 在声明在声明一个变量的引用后,在本函数执行期间,该引用一个变量的引用后,在本函数执行期间,该引用一直与其代表的变量相联系,不能再作为其他变一直与其代表的变量相联系,不能再作为其他变量的别名。下面的用法不对:量的别名。下面的用法不对:int a1,a2;int &b=a1;int &b=a2;(企图使企图使b变成变成a2的引用(别名)是不行的的引用(别名)是不行的)14.6.2 引用的简单使用引用的简单使用 通过下面的例子可以了解引用的简单使用。通过下面的例子可以了解引用的简单使用。 例例14.5 了解引用和变量的关系。了解引用和变量的关系。#inclu
35、de #include void main( ) int a=10; int &b=a;/声明声明b是是a的引用的引用 a=a*a; /a的值变化了,的值变化了,b的值也应一起变化的值也应一起变化 coutasetw(6)b; b=b/5; /b的值变化了,的值变化了,a的值也应一起变化的值也应一起变化 coutbsetw(6)a; a的值开始为的值开始为10,b是是a的引用,它的值当然也应该的引用,它的值当然也应该是是10,当,当a的值变为的值变为100(a*a的值)时,的值)时,b的值也的值也随之变为随之变为100。在输出。在输出a和和b的值后,的值后,b的值变为的值变为20,显然
36、显然a的值也应为的值也应为20(见图(见图14.1)。运行记录如下:)。运行记录如下:1001002020图图14.114.6.3 引用作为函数参数引用作为函数参数 有了变量名,为什么还需要一个别名呢?有了变量名,为什么还需要一个别名呢?c+之所之所以增加以增加“引用引用”, 主要是把它作为函数参数,以主要是把它作为函数参数,以扩充函数传递数据的功能。扩充函数传递数据的功能。 在在c语言中,函数的参数传递有以下两种情况。语言中,函数的参数传递有以下两种情况。 (1) 将变量名作为实参。这时传给形参的是变量的将变量名作为实参。这时传给形参的是变量的值。传递是单向的,在执行函数期间形参值发生值。传
37、递是单向的,在执行函数期间形参值发生变化并不传回给实参,因为在调用函数时,形参变化并不传回给实参,因为在调用函数时,形参和实参不是同一个存储单元。下面的程序无法实和实参不是同一个存储单元。下面的程序无法实现两个变量的值互换。现两个变量的值互换。 例例14.6 错误的程序。错误的程序。#include void swap(int a, int b)int temp; temp=a; a=b; b=temp;/实现实现a和和b的值互换的值互换void main( )int i=3,j=5; swap(i,j); couti,jendl; /i和和j的值未互换的值未互换 输出输出i和和j的值仍为的值
38、仍为3和和5。见图。见图14.2示意。图示意。图14.2(a) 表示调用函数时的数据传递,图表示调用函数时的数据传递,图14.2(b) 是执行是执行swap函数体后的情况,函数体后的情况,a和和b值的改变不会改变值的改变不会改变i和和j的值。的值。 为了解决这个问题,在第为了解决这个问题,在第10章介绍了传递变量地章介绍了传递变量地址的方法。址的方法。图图14.2 (2) 传递变量的指针。使形参得到一个变量的地址,传递变量的指针。使形参得到一个变量的地址,这时形参指针变量指向实参变量单元。见例这时形参指针变量指向实参变量单元。见例14.7。 例例14.7 使用指针变量作形参,实现两个变量的值使
39、用指针变量作形参,实现两个变量的值互换。互换。#include void swap(int *p1, int *p2)int temp; temp=*p1; *p1= *p2; *p2=temp;void main( )int i=3,j=5; swap(&i,&j); couti,jendl; 形参与实参的结合见图形参与实参的结合见图14.3示意。调用函数时把变示意。调用函数时把变量量i和和j的地址传送给形参的地址传送给形参p1和和p2(它们是指针变(它们是指针变量),因此量),因此*p1和和i为同一内存单元,为同一内存单元,*p2和和j为同一为同一内存单元,图内存单元,图1
40、4.3(a) 表示刚调用表示刚调用swap函数时的情函数时的情况,图况,图14.3(b) 表示执行完函数体语句时的情况。表示执行完函数体语句时的情况。图图14.3 显然,显然,i和和j的值改变了。的值改变了。 这种方法其实也是采用这种方法其实也是采用“值传递值传递”方式,向一个方式,向一个指针变量传送一个地址。然后再通过指针变量访指针变量传送一个地址。然后再通过指针变量访问有关变量。这样做能得到正确结果,但是在概问有关变量。这样做能得到正确结果,但是在概念上念上“兜了一个圈子兜了一个圈子” ,不那么直截了当。在,不那么直截了当。在pascal语言中有语言中有“值形参值形参”和和“变量形参变量形
41、参”(即(即var形参)形参) ,对应两种不同的传递方式,前者采用,对应两种不同的传递方式,前者采用值传递方式,后者采用地址传递方式(传送的是值传递方式,后者采用地址传递方式(传送的是变量的地址而不是变量的值,使形参指向一个变变量的地址而不是变量的值,使形参指向一个变量)。在量)。在c语言中,只有语言中,只有“值形参值形参”而无而无“变量形变量形参参”,全部采用值传递方式。,全部采用值传递方式。c+把引用型变量作把引用型变量作为函数形参,就弥补了这个不足。为函数形参,就弥补了这个不足。 c+提供了向函数传递数据的第三种方法,即传送提供了向函数传递数据的第三种方法,即传送变量的别名。变量的别名。
42、 例例14.8 利用利用“引用形参引用形参”实现两个变量的值互换。实现两个变量的值互换。#include void swap(int &a, int &b)int temp; temp=a; a=b; b=temp;void main( )int i=3,j=5; swap(i, j); couti=i j=jendl; 输出结果为输出结果为i=5 j=3 在在swap函数的形参表列中声明变量函数的形参表列中声明变量a和和b 是整型的是整型的引用变量(和其他变量一样,既可以在函数体中引用变量(和其他变量一样,既可以在函数体中声明变量的类型,也可以在定义函数时在形参表声明变量的类
43、型,也可以在定义函数时在形参表列中声明变量的类型)。图列中声明变量的类型)。图14.4请注意:在此处请注意:在此处&a不是不是“a的地址的地址”,而是指,而是指“a是一个引用型变是一个引用型变量量”。 但是此时并未对它们初始化,即未指定它但是此时并未对它们初始化,即未指定它们是哪个变量的别名。当们是哪个变量的别名。当main函数调用函数调用swap函数函数时由实参把变量名传给形参。时由实参把变量名传给形参。i的名字传给引用变的名字传给引用变量量a,这样,这样a就成了就成了i的别名。同理,的别名。同理,b成为成为j的别名。的别名。a和和i代表同一个变量,代表同一个变量,b和和j代表同一个
44、变量。在代表同一个变量。在swap函数中使函数中使a和和b的值对换,显然,的值对换,显然,i和和j的值同时的值同时改变了(见图改变了(见图14.4示意,其中示意,其中(a)是刚开始执行是刚开始执行swap函数时的情况,函数时的情况,(b)是执行完函数体语句时的是执行完函数体语句时的情况)。在情况)。在main函数中输出函数中输出i和和j已改变了的值。已改变了的值。 实际上,实参传给形参的是变量的地址,也就是实际上,实参传给形参的是变量的地址,也就是使形参使形参a具有变量具有变量i的地址,从而使的地址,从而使a和和i共享同一单共享同一单元。为便于理解,我们说把变量元。为便于理解,我们说把变量i的
45、名字传给引用的名字传给引用变量变量a,使,使a成为成为i的别名。请注意这种传递方式和的别名。请注意这种传递方式和使用指针变量作形参时有什么不同?分析例使用指针变量作形参时有什么不同?分析例14.8(对比例(对比例14.7),可以发现:),可以发现: 不必在不必在swap函数函数中设立指针变量,指针变量要另外开辟内存单元,中设立指针变量,指针变量要另外开辟内存单元,其内容是地址。而引用变量不是一个独立的变量,其内容是地址。而引用变量不是一个独立的变量,不单独占内存单元,在本例中其值为一整数。不单独占内存单元,在本例中其值为一整数。 在在main函数中调用函数中调用swap函数时实参不必在变量名函
46、数时实参不必在变量名前加前加&以表示地址。这种传递方式相当于以表示地址。这种传递方式相当于pascal语言中的语言中的“变量形参变量形参”,系统传送的是实参的地,系统传送的是实参的地址而不是实参的值。显然,这种用法比使用指针址而不是实参的值。显然,这种用法比使用指针变量简单、直观、方便。变量简单、直观、方便。 当读者看到当读者看到&a这样的形式时,怎样区别是声明引这样的形式时,怎样区别是声明引用变量还是取地址的操作呢?请记住,当用变量还是取地址的操作呢?请记住,当&a的前的前面有类型符时(如面有类型符时(如int &a),它必然是对引用的声),它必然是对引用的声
47、明;如果前面无类型符(如明;如果前面无类型符(如&a),则是取变量的),则是取变量的地址。地址。14.7 内内 置置 函函 数数 调用函数时需要一定的时间,如果有的函数需要调用函数时需要一定的时间,如果有的函数需要频繁使用,则所用时间会很长,从而降低程序的频繁使用,则所用时间会很长,从而降低程序的执行效率。执行效率。c+提供一种提高效率的方法,即在编提供一种提高效率的方法,即在编译时将所调用函数的代码嵌入到主调函数中。这译时将所调用函数的代码嵌入到主调函数中。这种嵌入到主调函数中的函数称为内置函数种嵌入到主调函数中的函数称为内置函数(inline function),又称内嵌函数。在有
48、些书中把它译成,又称内嵌函数。在有些书中把它译成“内联函数内联函数”。 指定内置函数的方法很简单,只需在函数首行的指定内置函数的方法很简单,只需在函数首行的左端加一个关键字左端加一个关键字inline即可。即可。 例例14.9 将函数指定为内置函数。将函数指定为内置函数。#include inline int max(int a, int b, int c) /这是一个内置函数,这是一个内置函数,求求3个整数中的最大者个整数中的最大者 if (ba) a=b; if (ca) a=c; return a; void main( )int i=7, j=10, k=25, m ; m=max(i
49、, j, k); coutmax=mi) i=j;if(ki) i=k;m=i; 内置函数与宏替换有些相似,但不完全相同。宏内置函数与宏替换有些相似,但不完全相同。宏替换是在编译前由预处理程序进行预处理,它只替换是在编译前由预处理程序进行预处理,它只作简单的字符替换而不作语法检查。而内置函数作简单的字符替换而不作语法检查。而内置函数是在编译时处理的,编译程序能识别内置函数,是在编译时处理的,编译程序能识别内置函数,对它进行语法检查。有些问题既可以用宏来处理,对它进行语法检查。有些问题既可以用宏来处理,也可以用内置函数处理,显然,内置函数优于宏也可以用内置函数处理,显然,内置函数优于宏替换,它不
50、会出现宏替换中可能产生的副作用。替换,它不会出现宏替换中可能产生的副作用。 使用内置函数可以节省运行时间,但却增加了目使用内置函数可以节省运行时间,但却增加了目标程序的长度。假设要调用标程序的长度。假设要调用10次次max函数,则在编函数,则在编译时先后译时先后10次将次将max的代码复制并插入的代码复制并插入main函数,函数,大大增加了大大增加了main函数的长度。因此只用于规模很函数的长度。因此只用于规模很小而使用频繁的函数,可大大提高运行速度。小而使用频繁的函数,可大大提高运行速度。14.8 作用域运算符作用域运算符 每一个变量都有其有效的作用域,只能在变量的每一个变量都有其有效的作用
51、域,只能在变量的作用域内使用该变量,不能直接使用其他作用域作用域内使用该变量,不能直接使用其他作用域中的变量。例如:中的变量。例如:#include float a=13.5;void main( )int a=5; couta; 程序中有两个程序中有两个a变量:一个是全局变量变量:一个是全局变量a,实型;,实型;另一个是另一个是main函数中的整型变量函数中的整型变量a,它是在,它是在main函函数中有效的局部变量。根据规定,在数中有效的局部变量。根据规定,在main函数中函数中局部变量将屏蔽全局变量。因此用局部变量将屏蔽全局变量。因此用cout输出的将是输出的将是局部变量局部变量a的值的值
52、5,而不是实型变量的值,而不是实型变量的值13.5。如果。如果想输出全局实型变量的值,有什么办法呢?想输出全局实型变量的值,有什么办法呢?c+提提供作用域运算符供作用域运算符 ,它能指定所需要的作用域。,它能指定所需要的作用域。可以把可以把main函数改为函数改为:void main( )int a=5; coutaendl; cout aendl; 运行时输出:运行时输出:5(局部变量(局部变量a的值)的值)13.5 (全局变量(全局变量a的值)的值) a表示全局作用域中的变量表示全局作用域中的变量a。请注意:不能用。请注意:不能用 访问函数中的局部变量。访问函数中的局部变量。14.9 动态
53、分配动态分配/撤销内存的运算符撤销内存的运算符new和和delete 在软件开发中,常常需要动态地分配和撤销内存空在软件开发中,常常需要动态地分配和撤销内存空间。在第间。在第11章中已知章中已知c语言中是利用库函数语言中是利用库函数malloc和和free分配和撤销内存空间的。但是使用分配和撤销内存空间的。但是使用malloc函数时函数时必须指定需要开辟的内存空间的大小。其调用形式必须指定需要开辟的内存空间的大小。其调用形式为为malloc(size) 。size是字节数,需要人们事先求出是字节数,需要人们事先求出或用或用sizeof运算符由系统求出。此外,运算符由系统求出。此外,malloc
54、函数只函数只能从用户处知道应开辟空间的大小而不知道数据的能从用户处知道应开辟空间的大小而不知道数据的类型,因此无法使其返回的指针指向具体的数据。类型,因此无法使其返回的指针指向具体的数据。其返回值一律为其返回值一律为void *类型,必须在程序中进行强类型,必须在程序中进行强制类型转换,才能使其返回的指针指向具体的数据。制类型转换,才能使其返回的指针指向具体的数据。 c+提供了较简便而功能较强的运算符提供了较简便而功能较强的运算符new和和delete来取代来取代malloc和和free函数(为了与函数(为了与c语言兼容,仍保语言兼容,仍保留这两个函数)。例如:留这两个函数)。例如: new
55、int; (开辟一个存放整数的空间,返回(开辟一个存放整数的空间,返回一个指向整型数据的指针)一个指向整型数据的指针) new int(100); (开辟一个存放整数的空间,并指(开辟一个存放整数的空间,并指定该整数的初值为定该整数的初值为100) new char10; (开辟一个存放字符数组的空间,(开辟一个存放字符数组的空间,该数组有该数组有10个元素,返回一个指向字符数据的指个元素,返回一个指向字符数据的指针)针) new int54; (开辟一个存放二维整型数组(开辟一个存放二维整型数组的空间,该数组大小为的空间,该数组大小为5*4) float *p=new float(3.14159) (开辟一个存放实数的(开辟一个存放实数的空间,并指定该实数的初值为空间,并指定该实数的初值为3.14159,将返回的,将返回的指向实型数据的指针赋给指针变量指向实型数据的指针赋给指针变量p) new运算符使用的一般格式为运算符使用的一般格式为new 类型类型 初值初值 用用new分配数组空间时不能指定初值。分配数组空间时不能指定初值。 delete运算符使用的一般格式为运算符使用的一般格式为delete 指针变量指
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 财政支出绩效报告范文
- 经典个人手车转让合同
- 学生故事教育课件
- 财务分析开题报告范文
- 比亚迪品牌调研报告范文
- 股权无偿转让的协议书
- 酒店装修工程2024年度承包服务协议
- 基于物联网的智能家居产品定制生产合同2024年度
- 基础汉语教育课件
- 煤矿设备维修服务合同2024
- 20米先简支后连续小箱梁上部施工方案
- 重点部位消防安全操作规程
- 天然气门站操作规程培训课件.doc
- 销售货物或者提供应税劳务清单(模板)
- JJF 1915-2021 倾角仪校准规范_(高清正版)
- “散打”教案
- ERCP插管技巧ppt课件
- 钢结构平台计算书
- 设备投放合作协议
- 教师对学生学习情况评价表3页
- 《Lou's Flu》RAZ分级阅读绘本pdf资源
评论
0/150
提交评论