C++程序设计:第14章 C++对C的扩充

上传人:公**** 文档编号:569814410 上传时间:2024-07-31 格式:PPT 页数:32 大小:166.50KB
返回 下载 相关 举报
C++程序设计:第14章 C++对C的扩充_第1页
第1页 / 共32页
C++程序设计:第14章 C++对C的扩充_第2页
第2页 / 共32页
C++程序设计:第14章 C++对C的扩充_第3页
第3页 / 共32页
C++程序设计:第14章 C++对C的扩充_第4页
第4页 / 共32页
C++程序设计:第14章 C++对C的扩充_第5页
第5页 / 共32页
点击查看更多>>
资源描述

《C++程序设计:第14章 C++对C的扩充》由会员分享,可在线阅读,更多相关《C++程序设计:第14章 C++对C的扩充(32页珍藏版)》请在金锄头文库上搜索。

1、第第1414章章 C+C+对对C C的扩充的扩充 C+与C语言的关系:C语言是C+的一个子集,C+包含了C语言的全部内容。1、C+保持与C语言的兼容,现有的许多C代码不经修改就可以为C+所用。 2、C+对C语言作了很多改进:增加了一些新的运算符,使得C+应用起来更加方便。改进了类型系统,增加了安全性。引进了“引用”概念,使用引用作函数参数带来了很大方便。允许函数重载,允许设置缺省参数,这些措施提高了编程的灵活性,减少冗余性。又引进了内联函数的概念,提高了程序的效率。对变量说明更加灵活了。可以根据需要随时对变量进行说明。 14.1 C+概述概述 14.2 C+程序结构程序结构n n例例例例14.

2、114.1n n /This is a C+ program. /This is a C+ program.n n #include #include n n void main( ) void main( )n n double x,y; double x,y;n n coutcoutEnter two float numbers:;xy;xy;n n double z=x+y; double z=x+y;n n coutcoutx+y=zx+y=zendlendl; ;n n n n运行结果:运行结果:n nEnter two float numbers:3.4 5.5Enter two

3、float numbers:3.4 5.5n nx+y=8.9x+y=8.9n n说明:说明:n n1 1)C+C+允许的新的注释形式以允许的新的注释形式以/ /开始,直到本行的末尾的开始,直到本行的末尾的文字都是注释。文字都是注释。n n2 2)iostream.hiostream.h是一个头文件,定义了标准的输入和输出操作,是一个头文件,定义了标准的输入和输出操作,包括对包括对cincin和和coutcout的说明。的说明。n n3 3)coutcout称为标准输出流,表示标准输出设备,一般指屏幕。称为标准输出流,表示标准输出设备,一般指屏幕。cincin表示标准输入设备,一般指键盘。表示

4、标准输入设备,一般指键盘。n n4 4)是重载的运算符,是重载的运算符,将键盘中输入的一个数,送到它右边的变量中保存将键盘中输入的一个数,送到它右边的变量中保存起来。起来。n n5 5)endlendl表示输出新行。表示输出新行。n nC+C+程序的源文件约定使用扩展名程序的源文件约定使用扩展名. .cppcpp或或. .cxxcxx,头文件约定头文件约定使用扩展名使用扩展名.h .h 或或. .hpphpp或或. .hxxhxx。编辑好的源程序经过编辑好的源程序经过C+C+编编译器编译成目标文件,其扩展名是译器编译成目标文件,其扩展名是. .objobj,再经过再经过C+C+连接器,连接器,

5、将目标文件与库文件中的一些代码连接起来,生成一个可将目标文件与库文件中的一些代码连接起来,生成一个可执行文件。程序被运行后,一般在屏幕上显示出运行结果。执行文件。程序被运行后,一般在屏幕上显示出运行结果。14.3 C+的的I/O流流cin和和coutn n在在C+C+中提供了新的输入中提供了新的输入/ /输出方式。其主要目标输出方式。其主要目标是建立一个类型安全、扩充性好的输入是建立一个类型安全、扩充性好的输入/ /输出系统。输出系统。C+C+的输入的输入/ /输出流库是建立在流的概念上。流类输出流库是建立在流的概念上。流类似于文件,可以把流看成是一个无限长的字符序列,似于文件,可以把流看成是

6、一个无限长的字符序列,它可以被顺序访问。从流中获取数据的操作称为提它可以被顺序访问。从流中获取数据的操作称为提取操作。向流中添加数据的操作称为插入操作。取操作。向流中添加数据的操作称为插入操作。C+C+的输入的输入/ /输出流库不是语言的一部分,而是作输出流库不是语言的一部分,而是作为一个独立的函数库提供的。因此,在使用时需要为一个独立的函数库提供的。因此,在使用时需要包含相应的头文件包含相应的头文件“ “iostream.hiostream.h” ”。输出操作被认输出操作被认为是插入过程,由重载的插入符为是插入过程,由重载的插入符“ “”来实现。来实现。 n n最一般的屏幕输出是将插入符作用

7、在流类的对象最一般的屏幕输出是将插入符作用在流类的对象coutcout上。例如:上。例如:n n#include #include n nmain()main()n n intint a=5,b=12; a=5,b=12;n ncoutcout“a=”aa=”ab=bb=bendlendl; ;n n最一般的键盘输入是将提取符作用在流类的对象最一般的键盘输入是将提取符作用在流类的对象cincin上。例如:上。例如:n n #include #include n n intint a,b; a,b;n n cincinab;ab;n n coutcoutababendlendl; ; n n提取

8、符可以连续写多个,每个后面跟一个表达式,提取符可以连续写多个,每个后面跟一个表达式,该表达式通常是获得输入值的变量或对象。该表达式通常是获得输入值的变量或对象。14.4函数的重载函数的重载 n n函数重载(函数重载(overloadingoverloading)是指一个函数可以和同一是指一个函数可以和同一作用域中的其他函数具有相同的名字,即同一个函作用域中的其他函数具有相同的名字,即同一个函数名可以对应着多个不同的函数实现。数名可以对应着多个不同的函数实现。C+C+中允许中允许两个或多个函数共用同一个函数名,但这些函数各两个或多个函数共用同一个函数名,但这些函数各自拥有可用于区分和唯一识别它们

9、的参数表。它们自拥有可用于区分和唯一识别它们的参数表。它们之间有的是通过参数表中某个参数的类型不同来区之间有的是通过参数表中某个参数的类型不同来区别,有的是通过参数个数的不同加以区别。别,有的是通过参数个数的不同加以区别。n n1 1、参数类型上不同的重载函数、参数类型上不同的重载函数、参数类型上不同的重载函数、参数类型上不同的重载函数n n例例例例14.214.2给函数名给函数名给函数名给函数名add()add()定义多个函数实现,该函数的功能是求定义多个函数实现,该函数的功能是求定义多个函数实现,该函数的功能是求定义多个函数实现,该函数的功能是求和。其中,一个函数实现求两个整型数之和,另一

10、个函数实和。其中,一个函数实现求两个整型数之和,另一个函数实和。其中,一个函数实现求两个整型数之和,另一个函数实和。其中,一个函数实现求两个整型数之和,另一个函数实现求两个浮点数之和。每种实现对应着一个函数体,这些函现求两个浮点数之和。每种实现对应着一个函数体,这些函现求两个浮点数之和。每种实现对应着一个函数体,这些函现求两个浮点数之和。每种实现对应着一个函数体,这些函数的名字相同,但是函数的参数的类型不同。这就是函数重数的名字相同,但是函数的参数的类型不同。这就是函数重数的名字相同,但是函数的参数的类型不同。这就是函数重数的名字相同,但是函数的参数的类型不同。这就是函数重载的概念。程序如下:

11、载的概念。程序如下:载的概念。程序如下:载的概念。程序如下:n n #include #include n n intint add(intadd(int , ,intint); );n n double add(double,double); double add(double,double);n n void main( ) void main( )n n coutcoutadd(3,6)add(3,6)endlendl; ;n ncoutcoutadd(4.6,9.0)add(4.6,9.0)endlendl; ; n nintint add(intadd(int a, a, intin

12、t b) b)n n return a+b; return a+b; n ndouble add(double a, double b)double add(double a, double b)n n return a+b; return a+b; n n程序运行结果如下:程序运行结果如下:n n 9 9n n13.6 13.6 n n2 2、参数个数上不同的重载函数、参数个数上不同的重载函数、参数个数上不同的重载函数、参数个数上不同的重载函数n n例例例例14.314.3找出几个找出几个intint型数中的最大者。型数中的最大者。n n#include #include n nintint

13、 max(intmax(int a, a, intint b); b);n nintint max(intmax(int a, a, intint b, b, intint c); c);n nvoid main( )void main( )n n coutcoutmax(12,6)max(12,6)endlendl; ;n n coutcoutmax(5,9,-12)max(5,9,-12)b?a:b; return ab?a:b; n nintint max(intmax(int a,inta,int b, b, intint c) c)n n intint t; t;n nif (a=b

14、) t=a;if (a=b) t=a;n n else t=b; else t=b;n n if (ct) t=c; if (ct) t=c;n n return t; return t; n n函数重载要求编译器能够唯一地确定调用一个函数时应执行函数重载要求编译器能够唯一地确定调用一个函数时应执行哪个函数代码,即采用哪个函数实现。确定函数实现时,要哪个函数代码,即采用哪个函数实现。确定函数实现时,要求从函数参数的个数和类型上来区分。也就是说,进行函数求从函数参数的个数和类型上来区分。也就是说,进行函数重载时,要求同名函数在参数个数上不同,或者参数类型上重载时,要求同名函数在参数个数上不同,或

15、者参数类型上不同。否则,将无法实现重载。不同。否则,将无法实现重载。n n使用函数重载主要是为了处理一组完成相同或相似功能的任使用函数重载主要是为了处理一组完成相同或相似功能的任务,但处理的数据个数或类型不同,这样,编程时可以不必务,但处理的数据个数或类型不同,这样,编程时可以不必费力的给它们起名和记忆。费力的给它们起名和记忆。n n如果两个函数参数个数和类型完全相同,仅仅是返回值不同,如果两个函数参数个数和类型完全相同,仅仅是返回值不同,它们不是重载的函数。程序中出现这样两个函数,编译时将它们不是重载的函数。程序中出现这样两个函数,编译时将出错。出错。n n函数重载可以使某些具有相似功能的函

16、数聚集起来共同使用函数重载可以使某些具有相似功能的函数聚集起来共同使用一个通常具有特定语义的函数名,但是当聚集起来的函数并一个通常具有特定语义的函数名,但是当聚集起来的函数并不执行相似的操作时,就不应采用函数重载。不执行相似的操作时,就不应采用函数重载。14.5 引用引用n n引用也是一种特殊类型的变量,它通常被认为是另一个引用也是一种特殊类型的变量,它通常被认为是另一个变量的别名。定义引用变量的格式:变量的别名。定义引用变量的格式:n n 类型类型 &引用名引用名= =变量名变量名; ;n n引用一般要立即进行初始化。无初始化的引用是无效的。引用一般要立即进行初始化。无初始化的引用是无效的。

17、n n引用与被引用的实体具有相同的地址,引用本身不能改引用与被引用的实体具有相同的地址,引用本身不能改变,所有在引用上所施加的操作,实质上就是在被引用变,所有在引用上所施加的操作,实质上就是在被引用者上的操作。者上的操作。 n n例如:例如: intint i=5 i=5,&m =i;&m =i;n n可以将一个引用赋给某个变量,则该变量将具有被引用可以将一个引用赋给某个变量,则该变量将具有被引用的变量的值。例如:的变量的值。例如: intint n=m; n=m;n n这时,这时,n n具有被具有被mm引用的变量引用的变量i i的值,即的值,即1010。n n例例例例14.414.4:n n

18、 #include #include n n void main() void main()n n intint i=5; i=5; n n intint & &ri ri=i;=i;n n coutcoutadd_i=&iadd_i=&iadd_riadd_ri=&=&ri riendlendl; ;n n coutcouti=ii=iri ri=ri riendlendl; ;n n i*=3; / i*=3; / 改变变量改变变量n n coutcouti=ii=iri ri=ri riendlendl; ;n n ri ri+=5;+=5;n n coutcouti=ii=iri ri

19、=ri riendlendl; ; n n运行结果:运行结果:n n add_i=63f974 add_i=63f974 add_riadd_ri=63f974=63f974n n i=5 i=5 ri ri=5=5n n i=15 i=15 ri ri=15=15n n i=20 i=20 ri ri=20=20n n从运行结果可以看出变量i 和引用ri的地址都是0x63f974,即这两个名字都标识的是地址为0x63f974的存储空间。所以不论对i改写,还是对ri的改写,都是操作在同一个程序实体上,即变量i和引用ri所指称的值都是相同的。n n例例例例14.514.5:n n #includ

20、e #include n n void main() void main()n n intint i=5; i=5;n n intint *pi=&i; *pi=&i;n n intint *& *&rpirpi=pi; /=pi; /对指针的引用对指针的引用n n coutcoutadd_pi=piadd_pi=piadd_rpiadd_rpi=rpirpiendlendl; ;n n coutcouti=ii=iendlendl; ;n n *pi=10; *pi=10;n n coutcouti=ii=iendlendl; ;n n * *rpirpi=20;=20;n n coutco

21、uti=ii=iendlendl; ; n n程序运行结果:程序运行结果:n n add_pi=63f970 add_pi=63f970 add_rpiadd_rpi=63f970=63f970n n i=5 i=5n n i=10 i=10n n i=20 i=20n n 由程序的运行结果可见,指针变量由程序的运行结果可见,指针变量pipi和引用和引用rpirpi的地址是相同的(的地址是相同的(0x63f9700x63f970),),也就是说,用于也就是说,用于存储指针的地址存储指针的地址0x63f9700x63f970具有两个字句具有两个字句pipi和和rpirpi。不论是对变量不论是对变

22、量i i操作,还是对操作,还是对pipi所指对象的操作所指对象的操作以及对以及对rpirpi所指对象的操作,都是对同一个程序所指对象的操作,都是对同一个程序实体的操作。实体的操作。 n nC+C+使用引用的主要地方是建立函数变参。将引用作为函数的使用引用的主要地方是建立函数变参。将引用作为函数的形参时,改变形参的值会影响实参的值。形参时,改变形参的值会影响实参的值。C+C+使用引用参数使用引用参数另一个目的是为了效率。如果函数的参数是类或结构类型,另一个目的是为了效率。如果函数的参数是类或结构类型,参数传递时将拷贝整个形参。使用引用可以只传递指向形参参数传递时将拷贝整个形参。使用引用可以只传递

23、指向形参的指针。引用调用是的指针。引用调用是C+C+中的一种函数调用方式,中的一种函数调用方式,C C语言中没语言中没有这种调用方式。有这种调用方式。n n例例例例14.614.6:函数参数是引用类型:函数参数是引用类型n n #include #include n n void void swap(intswap(int & &m,intm,int &n) / &n) /引用作函数的参数引用作函数的参数n n intint temp=m; temp=m;n nm=n;m=n;n nn=temp; n=temp; n nvoid main()void main()n n intint a=2,

24、b=4; a=2,b=4;n n swap(a,b); swap(a,b);n n coutcouta=aa=aendlendl; ;n n coutcoutb=bb=bendlendl; ; n n运算结果:运算结果:n n a=4a=4n n b=2 b=2n n使用引用作函数形参时,调用函数的实参要用变量名,将使用引用作函数形参时,调用函数的实参要用变量名,将实参变量名赋给形参的引用,相当于在被调用函数中使用实参变量名赋给形参的引用,相当于在被调用函数中使用了实参的别名。于是在被调用函数中,对引用的改变,实了实参的别名。于是在被调用函数中,对引用的改变,实质上就是直接地通过引用来改变实参

25、的变量值。而且这种质上就是直接地通过引用来改变实参的变量值。而且这种调用起到传址调用的作用,但它又比传址调用更方便、更调用起到传址调用的作用,但它又比传址调用更方便、更直接。因此,在直接。因此,在C+C+中常常使用引用作函数形参来实现在中常常使用引用作函数形参来实现在被调用函数中改变调用函数的实参值。被调用函数中改变调用函数的实参值。n n使用引用作形参但不改变实参值,可以如下定义函数原型:使用引用作形参但不改变实参值,可以如下定义函数原型:n n intint myFunc(constmyFunc(const intint & & paramparam); ); n n不能对不能对param

26、param赋值,否则编译出错。赋值,否则编译出错。n n引用可以作为函数的返回值。返回引用的函数可以作为引用可以作为函数的返回值。返回引用的函数可以作为左值,即它可以出现在赋值运算符的左边。左值,即它可以出现在赋值运算符的左边。n n例例例例14.714.7:n n #include #include n n intint a =1,3,5,7,9; a =1,3,5,7,9;n n intint & & elem(intelem(int i) / i) /函数返回引用类型函数返回引用类型n n return ai; return ai;n n void main() void main()n

27、 n intint j; j;n n for(j=1;j5;j+) for(j=1;j5;j+)n n elem(0)+= elem(0)+=elem(jelem(j); /); /返回引用的函数的函数调用返回引用的函数的函数调用可以出现在赋值运算符左边。可以出现在赋值运算符左边。n n coutcoutelem(0)=a0elem(0)=a0endlendl; ; n n在实现返回引用的函数时,注意不要返回对该函数内的在实现返回引用的函数时,注意不要返回对该函数内的自动变量的引用自动变量的引用, ,因为以后使用引用时,它所指向的变量因为以后使用引用时,它所指向的变量已不存在。已不存在。 14

28、.6内联函数内联函数n n引入内联函数的目的是为了解决程序中函数调用的效率引入内联函数的目的是为了解决程序中函数调用的效率问题。程序执行过程中,每调用一次函数,就要在调用问题。程序执行过程中,每调用一次函数,就要在调用与返回过程中付出一定的时间与空间代价用于处理现场。与返回过程中付出一定的时间与空间代价用于处理现场。当函数较小又反复使用时,处理现场的开销比重会急剧当函数较小又反复使用时,处理现场的开销比重会急剧增大。若把函数体嵌入函数调用处,便可以大大提高运增大。若把函数体嵌入函数调用处,便可以大大提高运行速度,节省开销。内联函数就可以自动实现这一功能。行速度,节省开销。内联函数就可以自动实现

29、这一功能。n n使用使用C+C+中新的关键字中新的关键字inlineinline说明的函数称为内联函数。说明的函数称为内联函数。编译器在遇到对内联函数调用时,将尽可能的用内联函编译器在遇到对内联函数调用时,将尽可能的用内联函数的函数体替换函数调用的表达式。因此会增加目标程数的函数体替换函数调用的表达式。因此会增加目标程序代码量,它是以目标代码的增加为代价来换取时间的序代码量,它是以目标代码的增加为代价来换取时间的节省。使用内联函数可以加快程序执行的速度。节省。使用内联函数可以加快程序执行的速度。 n n例例例例14.814.8:编程求:编程求110110中各个数的平方。中各个数的平方。n n#

30、include #include n ninline inline intint power_int(intpower_int(int x) x)n n return (x)*(x); return (x)*(x); n nvoid main()void main()n n intint i; i;n nfor(i=1;i=10;i+)for(i=1;i=10;i+)n n intint p= p=power_int(ipower_int(i); );n n coutcouti*i=pi*i=pendlendl; ; n n在使用内联函数时,应注意如下几点:在使用内联函数时,应注意如下几点:n

31、 n1 1、在内联函数内不允许用循环语句和开关语句。、在内联函数内不允许用循环语句和开关语句。n n2 2、内联函数的定义必须出现在内联函数第一次被调用之前。、内联函数的定义必须出现在内联函数第一次被调用之前。n n3 3、后面讲到的类结构中所有在类说明内部定义的函数都是、后面讲到的类结构中所有在类说明内部定义的函数都是内联函数。内联函数。 14.7函数参数的缺省值函数参数的缺省值n n正确的缺省参数说明:正确的缺省参数说明:n n void fun1(int void fun1(int x,intx,int y=0,int z=0); y=0,int z=0);n n void fun2(i

32、nt void fun2(int x,intx,int y=0); y=0);n nC+C+允许定义或说明函数时为一个或多个形参指定缺省值。允许定义或说明函数时为一个或多个形参指定缺省值。缺省参数的说明必须在形参表的最右边开始,并且中间没缺省参数的说明必须在形参表的最右边开始,并且中间没有间隔的非缺省参数说明。缺省参数只能定义一次,如果有间隔的非缺省参数说明。缺省参数只能定义一次,如果在函数原型中已经指定了缺省参数,那么在函数定义时不在函数原型中已经指定了缺省参数,那么在函数定义时不能再次说明。能再次说明。n n如果在函数调用时指定了形参对应的实参,则形参使用实如果在函数调用时指定了形参对应的

33、实参,则形参使用实参的值;如果未指定相应的实参,则形参使用缺省值。例参的值;如果未指定相应的实参,则形参使用缺省值。例如有如下的函数调用表达式:如有如下的函数调用表达式:n n fun1(10);fun1(10);n n 它与下列调用表达式是等价的:它与下列调用表达式是等价的:n n fun1(10,0,0);fun1(10,0,0);n n例例例例14.914.9:n n #include #include n n void void fun(intfun(int a=1,int b=3,int c=5) a=1,int b=3,int c=5)n n coutcouta=a,b=b,c=c

34、a=a,b=b,c=cendlendl; ; n n void main( ) void main( )n n fun( ); fun( );n n fun(7); fun(7);n n fun(7,9); fun(7,9);n n fun(7,9,11); fun(7,9,11);n n coutcoutOK!; OK!; n n执行该程序,输出如下结果:执行该程序,输出如下结果:n n a=1,b=3,c=5a=1,b=3,c=5n n a=7,b=3,c=5 a=7,b=3,c=5n n a=7,b=9,c=5 a=7,b=9,c=5n n a=7,b=9,c=11 a=7,b=9,c=

35、11n n OK! OK!n n 该程序中在函数的定义时设置了参数的缺省值,而在调用该程序中在函数的定义时设置了参数的缺省值,而在调用该函数时,有的无实参,有的实参数目不足,有的实参数目该函数时,有的无实参,有的实参数目不足,有的实参数目与形参相等,分若干不同情况来说明缺省值的使用。与形参相等,分若干不同情况来说明缺省值的使用。n n例例例例14.1014.10: :分析下列程序的输出结果:分析下列程序的输出结果:n n #include #include n n intint m(8); /* m(8); /*等价于:等价于:intint m=8; */ m=8; */n n intint

36、add_int(intadd_int(int x,intx,int y=7,int z=m); y=7,int z=m);n n void main( ) void main( )n n intint a(5),b(15),c(20); a(5),b(15),c(20);n n intint s= s=add_int(a,badd_int(a,b); );n n coutcoutssendlendl; ; n n intint add_int(intadd_int(int x,intx,int y,inty,int z) z)n n return x+y+z; return x+y+z; n

37、n该程序中,在说明函数该程序中,在说明函数add_intadd_int() ()时,给函数参数设时,给函数参数设置了缺省值,而其中一个参数的值被设置为一个已置了缺省值,而其中一个参数的值被设置为一个已知变量(知变量(mm)的值。的值。n n请读者自己分析该程序的输出结果。请读者自己分析该程序的输出结果。14. 8作用域运算符作用域运算符n n:是:是C+C+定义的一个新的运算符,称为作用域运算符。使用作定义的一个新的运算符,称为作用域运算符。使用作用域运算符可以访问当前作用域外部的标识符。当:作为单目用域运算符可以访问当前作用域外部的标识符。当:作为单目运算符时,它的右操作数是一个标识符,它限

38、定访问全局作用域运算符时,它的右操作数是一个标识符,它限定访问全局作用域范围内的该标识符。当:是双目运算符时,它的左操作数是类范围内的该标识符。当:是双目运算符时,它的左操作数是类名,右操作数是类的成员。它限定访问指定类的某个成员。:名,右操作数是类的成员。它限定访问指定类的某个成员。:运算符最有用的地方是在派生类中访问基类的成员。尤其是当派运算符最有用的地方是在派生类中访问基类的成员。尤其是当派生类定义的成员名字与基类中成员名字相同时(即派生类的成员生类定义的成员名字与基类中成员名字相同时(即派生类的成员名字覆盖基类的成员名字时)。名字覆盖基类的成员名字时)。n n例例例例14.1114.1

39、1:n nintint a, b; / a, b; /全局作用域内定义的变量全局作用域内定义的变量a,ba,bn nintint myClass:myFunc(intmyClass:myFunc(int a) a)n n myClass:amyClass:a=b; /=b; /当名字存在二义性时,使用:限定访问当名字存在二义性时,使用:限定访问的类的成员的类的成员n n :a=b; /:a=b; /访问的是全局作用域内定义的变量访问的是全局作用域内定义的变量a an n注意:在成员函数内访问全局变量是不好的程序设计风格,应尽注意:在成员函数内访问全局变量是不好的程序设计风格,应尽量避免。量避免

40、。14. 9 const修饰符定义常量修饰符定义常量n n使用类型修饰符使用类型修饰符constconst说明的类型称为常类型,常类型变量的值是说明的类型称为常类型,常类型变量的值是不能被更新的。因此,定义或说明常类型变量时必须进行初始化。不能被更新的。因此,定义或说明常类型变量时必须进行初始化。任何一种改变常类型变量的值的操作都将导致编译错误。例如:任何一种改变常类型变量的值的操作都将导致编译错误。例如:n n intint const m=15; const m=15;n n m=18; m=18;n n这种赋值操作是错误的。因为前面定义了这种赋值操作是错误的。因为前面定义了mm是一个常量

41、,并且给是一个常量,并且给它初始化了,即它初始化了,即mm值为值为1515,因此,不能再改变,因此,不能再改变mm的值了。的值了。n n一个没有初始化的常类型变量定义也会导致编译错误。例如:一个没有初始化的常类型变量定义也会导致编译错误。例如:n n const double PI; /error ; const double PI; /error ; uninitializeduninitialized const constn n试图把一个常类型变量的地址赋给一个指针同样会使编译器生成试图把一个常类型变量的地址赋给一个指针同样会使编译器生成编译错误。否则,常类型变量的值将通过指针间接地修改

42、。例如:编译错误。否则,常类型变量的值将通过指针间接地修改。例如:n n const const intint a=4; a=4;n n intint *p=&a; / error C2440: initializing : cannot convert from *p=&a; / error C2440: initializing : cannot convert from const const intint * to * to intint * *n n *p+=5; *p+=5;n n1 1、一般常量、一般常量n n一般常量是指简单类型的常量。这种常量在定义时,修饰符一般常量是指简单类

43、型的常量。这种常量在定义时,修饰符constconst可以用在类型说明符前,也可以用在类型说明符后。例可以用在类型说明符前,也可以用在类型说明符后。例如:如:n nintint const x=2; const x=2; 与与 const const intint x=2; x=2; 是一样的。是一样的。n nintint const a5=1,2,3,4,5; const a5=1,2,3,4,5;n n说明数组说明数组a a的各个元素是的各个元素是intint型常量,即数组元素的值是不能型常量,即数组元素的值是不能被更新的。被更新的。n n2 2、常指针、常指针n n使用使用constco

44、nst修饰指针时,由于修饰指针时,由于constconst的位置不同,而含意不同。的位置不同,而含意不同。n n下面定义的是一个指向字符串的常量指针:下面定义的是一个指向字符串的常量指针:n nchar *const ptr1=stringptr1;char *const ptr1=stringptr1;n n其中,其中,ptr1ptr1是一个常量指针。因此,下面赋值是非法的是一个常量指针。因此,下面赋值是非法的: :n nptr1=stringptr2;ptr1=stringptr2;n n而下面赋值是合法的而下面赋值是合法的: :n n *ptr1=m; *ptr1=m;n n因为指针因为

45、指针ptr1ptr1所指向的变量是可以更新的。所指向的变量是可以更新的。n n下面定义了一个指向字符串常量的指针:下面定义了一个指向字符串常量的指针:n nconst char *ptr2=stringptr1;const char *ptr2=stringptr1;n n其中,其中,ptr2ptr2是一个指向字符串常量的指针。是一个指向字符串常量的指针。ptr2ptr2所指所指向的字符串是不能更新的,而向的字符串是不能更新的,而ptr2ptr2是可以更新的。是可以更新的。因此,因此,n n* *ptr2=x;ptr2=x;n n是非法的。而是非法的。而n nptr2=stringstr2;p

46、tr2=stringstr2;n n是合法的。是合法的。n n所以,在使用所以,在使用constconst修饰指针时,应该注意修饰指针时,应该注意constconst的位的位置。定义一个指向字符串的指针常量和定义一个指置。定义一个指向字符串的指针常量和定义一个指向字符串常量的指针时,向字符串常量的指针时,constconst修饰符的位置不同,修饰符的位置不同,前者前者constconst放在放在* *和指针名之间,后者和指针名之间,后者constconst放在类型放在类型说明符前。说明符前。n n例例例例14.1214.12常指针作函数参数的例子。常指针作函数参数的例子。n n #includ

47、e #include n n const const intint N=6; N=6;n n void print(const void print(const intint * *p,intp,int n); n);n n void main() void main()n n intint arrayN; arrayN;n n for(intfor(int i=0;iN;i+) i=0;iarrayi;arrayi;n n print(array,N); print(array,N); n n void print(const void print(const intint * *p,int

48、p,int n) n)n n coutcout*p;*p;n n for(intfor(int i=1;in;i+) i=1;in;i+)n n coutcout,*(p+i);,*(p+i);n n coutcoutendlendl; ; n n执行该程序输入如下信息:执行该程序输入如下信息:n n1 2 3 4 5 6 1 2 3 4 5 6 n n输出结果如下:输出结果如下:n n1, 2, 3, 4, 5, 61, 2, 3, 4, 5, 6n n说明:该程序中两处出现说明:该程序中两处出现constconst修饰符,一是使用修饰符,一是使用constconst定义一个定义一个inti

49、nt型常量型常量N N;二是使用二是使用constconst定义一个指向常量数组的指针。该定义一个指向常量数组的指针。该指针所指向的数组元素是不能被更新的。指针所指向的数组元素是不能被更新的。n n该程序中有一个问题:该程序中有一个问题:print()print()函数中,实参函数中,实参arrayarray是一个是一个intint型数型数组名,形参是组名,形参是const const intint的指针,显然类型不相同,但却没有出的指针,显然类型不相同,但却没有出现类型错误。这是因为形参虽然是指向一个非现类型错误。这是因为形参虽然是指向一个非const const intint型数组型数组a

50、rrayarray,该数组是可以更新的,但在该数组是可以更新的,但在print()print()函数中不能被更新。函数中不能被更新。因此,一个能够更新的变量使用在一个不能被更新的环境中是因此,一个能够更新的变量使用在一个不能被更新的环境中是不破坏类型保护,所以不出现类型不匹配错。不破坏类型保护,所以不出现类型不匹配错。n n3 3、使用、使用constconst也可以说明引用,被说明的引用为常引用,该引也可以说明引用,被说明的引用为常引用,该引用所引用的对象不能被更新。用所引用的对象不能被更新。n n4 4、使用、使用constconst关键字进行说明的成员函数,称为常成员函数。关键字进行说明

51、的成员函数,称为常成员函数。只有常成员函数才有资格操作常量或常对象,没有使用只有常成员函数才有资格操作常量或常对象,没有使用constconst关关键字说明的成员函数不能用来操作常对象。键字说明的成员函数不能用来操作常对象。14.10动态内存分配和撤消运算符动态内存分配和撤消运算符new和和deleten n在在C+C+中,定义了两个新的运算符:中,定义了两个新的运算符:newnew和和deletedelete,专门进专门进行动态内存申请和释放,而且行动态内存申请和释放,而且newnew能自动调用构造函数创能自动调用构造函数创建相应的类对象,建相应的类对象,deletedelete能自动调用析

52、构函数删除类对象。能自动调用析构函数删除类对象。newnew和和deletedelete应匹配使用,如果应匹配使用,如果deletedelete运算符作用到不是用运算符作用到不是用newnew返回的指针,可能引起程序运行错误。返回的指针,可能引起程序运行错误。 n n动态申请保存一个动态申请保存一个typetype类型的数据的内存:类型的数据的内存:n n p=new type;p=new type;n np p是指向类型是指向类型typetype的指针,的指针,typetype是数据类型名。是数据类型名。n n释放以前用释放以前用newnew申请的保存一个申请的保存一个typetype类型数

53、据的内存:类型数据的内存:n n delete p;delete p;n n等号左边的类型必须与右边申请的类型一致,否则,编译等号左边的类型必须与右边申请的类型一致,否则,编译出错。出错。n nnew new 返回分配的内存地址,应该将它保存在一个变量中,返回分配的内存地址,应该将它保存在一个变量中,以后用以后用deletedelete释放。释放。 n n例例例例14.1314.13:n n#include #include n nvoid main()void main()n n intint *p; *p;n n p=new p=new intint; ;n n *p=888; *p=88

54、8;n n coutcoutadd_p=&padd_p=&pendlendl; ;n n coutcoutadd_m=padd_m=pendlendl; ;n n coutcoutvalue_*p=*pvalue_*p=*pendlendl; ;n n delete p; delete p; n n运行结果如下运行结果如下: :n nadd_p=0x0065fdf4add_p=0x0065fdf4n nadd_m=0x00780da0add_m=0x00780da0n nvalue_*p=888value_*p=888n nnewnew能自动计算它要分配的存储空间的大小,可以能自动计算它要分配

55、的存储空间的大小,可以为更复杂的数据实体(如数组)分配空间,如语为更复杂的数据实体(如数组)分配空间,如语句:句:n n intint *pi=new int8; *pi=new int8; n n动态分配存放动态分配存放8 8个整数的内存空间。释放个整数的内存空间。释放pipi指向的指向的数组存储区时,应使用下面的格式:数组存储区时,应使用下面的格式:n n delete pi;delete pi;n nnewnew可以在为简单变量动态分配内存空间的同时,可以在为简单变量动态分配内存空间的同时,进行初始化。例如:进行初始化。例如:n n intint *p=new int(10); *p=new int(10);n n在动态分配内存的同时,将这个动态存储区中的在动态分配内存的同时,将这个动态存储区中的值初始化为值初始化为1010。但是,不能用。但是,不能用newnew为动态分配的数为动态分配的数组存储区进行初始化。组存储区进行初始化。

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 高等教育 > 研究生课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号