版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第九章从C到C++9.1C++对C的一般扩充9.2C++中的函数9.3C++的输入与输出流9.4小结9.1C++对C的扩充
C++在C语言标识符的基础上,增加了许多标识符,下面列出常用的标识符。
asmcatchclassdelete
friendinlinenewoperator
privateprotectedpublictemplatevirtual特别注意,在将原来用C语言写的程序用C++编译之前,应把与上述关键字同名的标识符改名。9.1.1新增的关键字9.1.2注释在C语言中,我们用“/*”及“*/”作为注释分界符号,C++除了保留这种注释方式外,还提供了一种更有效的注释方式,即用“//”导引出单行注释。例如:
intx;/*定义一个整型变量*/
intx;//定义一个整型变量这两条语句是等价的。C++的“//…”注释方式特别适合于注释内容不超过一行的注释,这使语句显得很简洁。9.1.3类型转换C++支持两种不同的类型转换形式:
inti=0;
longl=(long)I;//C的类型转换
longm=long(i);//C++的新风格C++新风格的类型转换形式看上去象是一个函数调用,所以可读性较好。而且,这种形式也适合于用户定义类型的转换(用定义函数来实现)。9.1.4灵活的变量声明在C语言中,局部变量说明必须置于可执行代码段之前,不允许局部变量说明和可执行代码混合起来。但在C++中,允许在代码块的任何地方说明局部变量,也就是说,变量可以放在任何语句位置,不必非放在程序段的开始处。例如:voidf(){
inti;
i=1;
intj;
j=2;
//…}
这样,可以随用随定义,这也是C++封装的要求,易读性也好。而且在远离数据项被使用处的地方声明,易引起混淆或导致错误。9.1.5const1.const定义常量在C中,习惯使用#define来定义常量,例如:
#defineSIZE100;C++提供了一种更灵活、更安全的方式来定义变量,即使用类型限定符const来表示常量。所以,C++中的常量可以是有类型的,程序员不必再用#define创建无类型常量。例如:
constintsize=100;声明成const的变量,实际是常量,它有地址,可以用指针指向这个值,但在程序中是不可修改的。使用#define有时是不安全的,如下例所示。【例9.1】使用#define引起的歧义。#include<iostream.h>voidmain(){ inta=1;#defineT1a+a #defineT2T1-T1 cout<<"T2is"<<T2<<endl;}初看程序,似乎应输出:T2is0但是实际的输出结果是:T2is2【例9.2】使用const消除#define的不安全性。#include<iostream.h>voidmain(){ inta=1;constT1=a+a; constT2=T1-T1; cout<<"T2is"<<T2<<endl;}程序执行结果如下:T2is02.const修饰指针 const还可以修饰指针的情况,例如:
intb=500; constint*a=&b;
① intconst*a=&
b;
② int*consta=&b;
③ constint*consta=&b;
④const修饰指针的情况可以有以上几种形式,①和②的情况相同,都是指针所指向的内容为常量,这种情况下不允许对指针指向的内容进行更改操作,如不能:*a=3;但是,由于a是一个指向常量的普通指针变量,不是常指针,因此可以改变a的值,例如下列语句是允许的:
intc=3; a=&c;上述③为指针本身是常量,即常指针,而指针所指向的内容不是常量,这种情况下不能对指针本身进行更改操作,例如:
a++;
//非法但是它指向的数据可以改变,例如:
*a=3;//合法 是可以的。上述④为指针本身和指向的内容均为常量,均不能修改。不难理解以下两个语句都是错误的:
a++;
//非法
*a=3;//非法3.const在函数中的应用const还常用来限定函数的参数和返回值。函数参数如果使用const声明,说明在函数中不能修改该参数。例如:
floatfun(constfloatx) {returnx*x;}//非法:x=x*x;如果函数返回基本类型(如int和double),用const声明返回值没有特别的意义,但如果函数返回一个指针或引用(引用的概念在后面提及),则使用const声明返回值表示调用函数时不能用返回值来改变返回值所指向或引用的变量。例如:
constint*fun() { staticintx=1; ++x; return&x; } voidmain() { inty; y=*fun();//合法:将值x赋值给y *fun()=2;//非法:不能改变一个常量的类型 }9.1.6struct
C++的struct后的标识符可看作是类型名,所以定义某个变量比C中更加直观。例如,在C中:
structpoint{intx;inty};structpointp;而在C++中:
structpoint{intx;inty};pointp;我们不必再写struct。对于union,也可以照此使用。9.1.7作用域分辨运算符“::”“::”是作用域分辨运算符,它用于访问在当前作用域中被隐藏的数据项。如果有两个同名变量,一个是全局的,另一个是局部的,那么局部变量在其作用域内具有较高的优先权。【例9.3】局部变量在其作用域内具有较高的优先权。
#include<iostream.h>inta=10;//全局变量aintmain(){ inta;a=25;//局部变量a cout<<"ais"<<a<<endl;return0;}程序执行结果如下:ais25【例9.4】使用域作用运算符#include<iostream.h>inta;//全局变量aintmain(){ inta;a=25;//局部变量a ::a=10;//全局变量a cout<<"localis"<<a<<endl; cout<<"globalis"<<::a<<endl;return0;}程序执行结果如下:localis25globalis109.1.8C++的动态内存分配C程序中,动态内存分配是通过调用malloc()和free()等库函数来实现的,而C++给出了使用new
和delete运算符进行动态内存分配的新方法。例9.5用malloc()实现内存分配。#include<stdio.h>#include<malloc.h>voidmain(){ int*p; p=(int*)malloc(sizeof(int)); *p=10; printf("%d",*p); free(p);}运算符new用于内存分配的使用形式为:
p=newtype;其中,type是一个数据类型名,p是指向该数据类型的指针。new从内存中为程序分配一块sizeof(type)字节大小的内存,该块内存的首地址存于指针p中。运算符delete用于释放new分配的存储空间,它的使用形式为:
deletep;其中,p必须是一个指针,保存着new分配的内存的首地址。以下是C++程序中用新方法实现动态内存分配的例子。【例9.6】用new实现动态内存分配。#include<iostream.h>voidmain(){ int*i=newint;//为指针i分配存储空间 *i=10; cout<<*i; deletei;//释放i指向的存储空间}说明:(1)使用new可以为数组动态分配存储空间,这时需要在类型名后缀上数组的大小。例如:int*p=newint[10];这时new为具有10个元素的整型数组分配了内存空间,并将首地址赋给了指针p。
需要注意的是,使用new给多维数组分配空间时,必须提供所有维的大小,如:
int*p=newint[2][3][4];其中第一维的界值可以是任何合法的表达式。
inti=3;int*p=newint[i][3][4];(2)new可以在为简单变量分配内存的同时,进行初始化。例如:int*p=newint(99);new分配了一个整型内存空间,并赋初始值99。但是,new不能对动态分配的数组存储区进行初始化。(3)释放动态分配的数组存储区时,可用如下的delete格式:
delete[]p;(4)使用new动态分配内存时,如果分配失败,既没有足够的内存空间满足分配要求,new将返回空指针(NULL)。因此通常要对内存的动态分配是否成功进行检查。intmain(){
int*p=newint;//为指针p分配存储空间
if(!p){cout<<"分配失败"<<endl;return1;}*p=10;cout<<*p;deletep;//释放p指向的存储空间
return0;}9.1.9引用
在前面的章节中,我们学习了指针的概念,指针就是内存单元的地址,它可能是变量的地址,也可能是函数的入口地址。这里看另外一个同指针相关的概念:引用。在引入引用的概念之前,我们先看一个例子。【例9.7】值传递应用#include<iostream.h>voidswap(intm,intn){ inttemp; temp=m; m=n; n=temp;}intmain(){ inta=5,b=10; cout<<"a="<<a;cout<<"b="<<b<<endl; swap(a,b); cout<<"a="<<a;
cout<<"b="<<b<<endl;
return0;}程序执行结果如下:a=5b=10a=5b=10【例9.】8使用指针(地址)进行值传递#include<iostream.h>voidswap(int*m,int*n){ inttemp; temp=*m; *m=*n; *n=temp;}intmain(){ inta=5,b=10;cout<<"a="<<a;cout<<"b="<<b<<endl; swap(&a,&b); cout<<"a="<<a;cout<<"b="<<b<<endl;return0;}程序执行结果如下:a=5b=10a=10b=5引用是能自动间接引用的一种指针。自动间接引用就是不必使用间接引用运算符*,就可以得到一个引用值。我们可以这样理解,引用就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样。那么,在程序设计的时候,引用如何定义并使用呢?1.引用的定义定义引用的关键字是“type&”,它的含义是“type类型的引用”,此引用与type类型的对象或变量的地址相联系。例如:
inti=5;int&j=i;它创建了一个整型引用,j是i的别名,i和j占用内存同一位置。当i变化时,j也随之变化,反之亦然。引用的初始值可以是一个变量或另一个引用,以下的定义也正确。
inti=5;int&j=i;int&j1=j;2.使用规则(1)定义引用时,必须立即初始化。 inti; int&j;//错误,没有初始化 j=i;(2)引用不可重新赋值。 inti,k; int&j=i; j=&k;//错误,重新赋值(3)引用不同于普通变量,下面的声明是非法的:
int&b[3];//不能建立引用数组 int&*P;//不能建立指向引用的指针 int&&r;//不能建立指向引用的引用(4)当使用&运算符取一个引用的地址时,其值为所引用的变量的地址。
intnum=50;int&ref=num;int*p=&ref;则p中保存的是变量num的地址。【例9.9】引用传递#include<iostream.h>voidswap(int&m,int&n){ inttemp; temp=m; m=n; n=temp;}main(){inta=5,b=10;cout<<"a="<<a;cout<<"b="<<b<<endl;swap(a,b);cout<<"a="<<a;cout<<"b="<<b<<endl;return0;}程序执行结果如下:a=5b=10a=10b=59.2C++中的函数C对main()函数的格式并无特殊规定,因为通常C不关心返回何种状态给操作系统。然而,C++却要求main()函数匹配下面两种原型之一。
voidmain() //无参数,无返回类型
intmain(intargc,char*argv[])
//带参数,有返回类型,参数也可以省略。9.2.1主函数main
第二种main()函数中形参argc是命令行总的参数个数,argv[]是大小为argc,其中第0个参数存储的是程序的全名,其后存储的是程序名后所带的参数。
例如,包含第二种main()函数的程序test.exe,在命令行方式下执行时输入:
C:\>test
a.c
b.c
t.c
则
argc
=4,argv[0]="test",argv[1]
="a.c"
,argv[2]="b.c"
,argv[3]="t.c"。
如果main()前面不写返回类型,那么main()等价于
intmain()
函数要求具有int返回类型,如例9.9。9.2.2函数定义C++函数定义中的参数说明必须放在函数名后的括号内,不可将函数参数说明放在函数说明部分与函数体之间,如:voidfun(a)inta;//错误的参数说明方式{}但在C中,这种说明方法是允许的。9.2.3内置函数函数调用导致了一定数量的额外开销,如参数入栈、出栈等。有时,正是这种额外开销迫使C程序员在整个程序中复制代码以提高效率。C++的内置函数正是为了解决这一问题而提供的。当函数定义是由inline开头时,表明此函数为内置函数。编译时,使用函数体中的代码替代函数调用表达式,从而完成与函数调用相同的功能,这样,能加快代码的执行,减少调用开销。例如:inlineintsum(inta,intb)//内置函数{returna+b;}说明:①内置函数必须在它被调用之前定义,否则编译不会得到预想的结果。②若内置函数较长,且调用太频繁时,程序将加长很多,通常只有较短的函数才定义为内置函数,较长的函数最好作为一般函数处理。9.3.4缺省参数值
C++对C函数的一大重要的改进之一就是可以为函数定义缺省的参数值。例如:
intfun(intx=5,inty=10);
//函数原型,给出缺省的参数值x与y的值分别是5和10。当进行函数调用时,编译器按从左向右顺序将实参与形参结合,若未指定足够的实参,则编译器按顺序用函数原型中的缺省值来补足所缺少的实参。例如:
fun(1,2);//x=1,y=2fun(1);//x=1,y=10fun();//x=5,y=10一个C++函数可以有多个缺省参数,并且C++要求缺省参数必须连续的放在函数参数表的尾部,也就是说,所有取缺省值的参数都必须出现在不取缺省值的参数的右边。当调用具有多个缺省参数时,若某个参数省略,则其后的参数皆应省略而采用缺省值。当不允许出现某个参数省略时,再对其后的参数指定参数值。例如:
fun(,5)//这种调用方式是错误的9.2.5函数重载在C语言中,函数名必须是唯一的,也就是说不允许出现同名的函数。当要求编写求整数、浮点数和双精度浮点数的立方数的函数时,若用C语言来处理,必须编写三个函数,这三个函数的函数名不允许同名。例如:Icube(inti);//求整数的三次方Fcube(floatf);//求浮点数的三次方Dcube(doublei);//求双精度浮点数的三次方在C++中,用户可以重载函数,这意味着,只要函数参数的类型不同,或者参数的个数不同,两个或两个以上的函数可以使用相同的函数名。【例9.10】重载cube函数。#include<iostream.h>intcube(inti){returni*i*i;}floatcube(floatf){returnf*f*f;}doublecube(doubled){returnd*d*d;}intmain(){ inti=12; floatf=3.4; doubled=5.678; cout<<i<<'*'<<i<<'*'<<i<<'='<<cube(i)<<endl; cout<<f<<'*'<<f<<'*'<<f<<'='<<cube(f)<<endl; cout<<d<<'*'<<d<<'*'<<d<<'='<<cube(d)<<endl; return0;}值得注意,重载函数应在参数个数或参数类型上有所不同,否则编译程序将无法确定调用哪一个重载版本,即使返回类型不同,也不能区分。例如:intfun(intx,inty);doublefun(intx,inty);其重载函数的参数个数类型相同,是错误的。另外,同函数名同参数表的const和非const成员函数也可构成重载。例如:
intmyclass::fun(inta,intb);intmyclass::fun(inta,intb)const;9.3C++的输入与输出流大家都知道C语言提供了强有力的I/O函数,其功能强,灵活性好,是很多语言无法比拟的。但是,在C语言中进行I/O操作时,常会出现以下错误:
inti; floatf; scanf("%f",i); /*i是int型,"%f"应该是"%d",i应该是&i*/ printf("%d",f); /*f是float型,"%d"应该是"%f"*/cin使用C++的I/O系统,可以将上面的操作写成: inti; floatf; cin>>i; cout<<f;这里的cin是标准的输入流,在程序中用于代表标准输入设备,即键盘。运算符“>>”是输入运算符,表示从标准输入流(即键盘)读取的数值传送给右方指定的变量。运算符“>>”允许用户连续读入一连串数据,两个数据间用空格、回车或Tab键分隔。例如:
cin>>x>>y;coutcout是标准的输出流,在程序中用于代表标准输出设备,通常指屏幕。运算符“<<”是输出运算符,表示将右方变量的值显示到屏幕上。运算符“<<”允许用户连续输出数据。例如:cout<<x<<y;这里的变量应该是基本数据类型,不能是void型。为了支持类的概念,C++系统建立了一个可扩展的输入输出系统,它可以通过修改和扩展来加入用户自定义类型并进行相应操作。例如,在C语言中有下面结构类型变量的定义: structpoint { intx,y; }a;这里,无法延伸C语言的I/O系统,使之直接在变量a上执行I/O操作,如下面的用法是错误的:
printf("%point",a);9.3.1C++的流类结构虽然,C++语言和C语言的I/O系统有着显著的差异,但它们也有着共同之处,即都是对流(tream)进行操作。流实际上就是一个字节序列。输入操作中,字节从输入设备(如键盘、磁盘、网络连接等)流向内存;输出操作中,字节从内存流向输出设备。使用C++的I/O的系统必须包含头文件iostream.h,对某些流函数可能还需要其他头文件,例如进行文件I/O时需要头文件fstream.h。1.iostream库iostream库中具有streambuf和ios两个平行的类,这都是基本的类,分别完成不同的工作。streambuf类提供基本流操作,但不提供格式支持。ios类为格式化I/O提供基本操作。2.标准流iostream.h说明了标准流对象cin、cout、cerr与clog。cin是标准输入流,对应于C语言的stdin;cout是标准输出流,对应于C语言的stdout;cerr是标准出错信息输出,clog是带缓冲的标准出错信息输出。cerr和clog流被连到标准输出设备上,对应于C语言的stderr。cerr和clog之间的区别是cerr没有缓冲,发送给它的任何输出立即被执行,而clog只有当缓冲区满时才有输出。缺省时,C++语言标准流被连到控制台上。9.3.2格式化I/O1.状态标志字enum{skipws=0x0001,left=0x0002, right=0x0004,internal=0x0008, dec=0x0010,oct=0x0020, hex=0x0040,showbase=0x0080, showpoint=0x0100, uppercase=0x0200,showpos=0x0400, scientific=0x0800, fixed=0x1000,unitbuf=0x2000, stdio=0x4000, }2.ios类中用于控制输入输出格式的成员函数
(1)设置状态标志setf(longflags)。(2)清除状态标志unsetf()。(3)取状态标志flags()。(4)设置域宽width()。(5)设置显示的精度precision(intnum);(6)填充字符fill()。【例9.11】设置状态标志。#include<iostream.h>voidmain(){ cout.setf(ios::showpos|ios::scientific); cout<<123<<""<<123.456<<endl; }【例9.12】使用ios类中用于控制输入输出格式的成员函数#include<iostream.h>voidmain(){ cout<<"x_width="<<cout.width()<<endl; cout<<"x_fill="<<cout.fill()<<endl; cout<<"x_precision="<<cout.precision()<<endl; cout<<123<<""<<123.45678<<endl; cout<<"-------------------------"<<endl;
cout<<"****x_width=10,x_fill=&,x_precision=4****"<<endl; cout.fill('&'); cout.width(10);cout.setf(ios::scientific); cout.precision(4); cout<<123<<""<<123.45678<<endl; cout.setf(ios::left); cout.width(10); cout<<123<<""<<123.45678<<endl; cout<<"x_width="<<cout.width()<<endl; cout<<"x_fill="<<cout.fill()<<endl; cout<<"x_precision="<<cout.precision()<<endl;}3.用操作子进行格式化C++流类库所定义操作子如下:dec,hex,oct:数值数据采用十进制、十六进制、八进制表示,可用于输入或输出。ws:提取空白符,仅用于输入。endl:插入一个换行符并刷新输出流,仅用于输出。ends:插入空字符,仅用于输出。flush:刷新与流相关联的缓冲区,仅用于输出。setbase(intn):设置数值转换基数为n(n的取值为0、8、10、16),0表示使用缺省基数,
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年度扶贫资金管理及使用专项合同3篇
- 2025年度智能广告创意制作与推广服务合同4篇
- 2024铺位出租合同-亲子乐园铺位租赁管理协议3篇
- 2025年度石材加工与大理石施工一体化工程合同4篇
- 2025年度土地整治与修复项目租赁合同4篇
- 2025年度智能生产线承包运营服务合同4篇
- 2024版货车租赁合规性及责任明确合同版B版
- 2025年度水电安装工程智能化施工技术与保修服务合同3篇
- 2025年度智能物流配套厂房建设合同范本4篇
- 2025年度智能家居瓷砖批发代理销售合同3篇
- 使用错误评估报告(可用性工程)模版
- 公司章程(二个股东模板)
- GB/T 19889.7-2005声学建筑和建筑构件隔声测量第7部分:楼板撞击声隔声的现场测量
- 世界奥林匹克数学竞赛6年级试题
- 药用植物学-课件
- 文化差异与跨文化交际课件(完整版)
- 国货彩瞳美妆化消费趋势洞察报告
- 云南省就业创业失业登记申请表
- UL_标准(1026)家用电器中文版本
- 国网三个项目部标准化手册(课堂PPT)
- 快速了解陌生行业的方法论及示例PPT课件
评论
0/150
提交评论