




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、面向对象程序程序设计及C+,主讲:俞琼,第2章 C+对C的改进及扩展,面向对象程序设计及C+,3,本章内容提要,新增的I/O控制方法及单行注释方法 const的灵活应用 在类型上的变化与增加 函数的新用法和要求:原型声明、内联函数、函数重载、默认参数值 新增引用的灵活应用 更加方便的动态内存空间的管理 异常处理的机制和方法,4,本章内容安排,2.1 新的输入/输出及注释方式 2.2 独具魅力的const修饰符 2.3 有关类型的区别 2.4 有关函数的区别 2.5 新增引用的灵活运用 2.6 动态内存空间管理 2.7 C+的异常处理 2.8 本章小结,结束本章,5,2.1.1 C+的I/O流实
2、现输入/输出,例2.1-理解C+更为方便的输入输出控制方式 【例2.1】C+语言风格与C语言风格的源程序举例。 /*C语言风格的源程序li2_1.c,读入几个变量,运算后输出*/ #include void main( ) char c; int a; /*定义变量c、a、f */ float f; scanf(%c%d%f, ,cincaf ;,coutc=c a=a f=fendl ;,/*li2_1.cpp : C+语言风格源程序,与li2_1.c实现同样功能*/,/定义变量c、a、f,#include using namespace std;,6,2.1.1 C+的I/O流实现输入/输
3、出,区别: C+源程序 C源程序 扩展名 .cpp .c。 输入 cin scanf 输出 cout printf 注释 以/开头的单行注释,7,C+的I/O操作,首先要作文件包含:#include 输入方式:cin变量1变量2; 输出方式:cout输出项1输出项2 ;,此处为输入运算符,允许用户输入数据给变量,输入多个数据时以空格、回车、Tab键分隔,此处为输出运算符,允许用户输出一连串数据,输出项可以是常量、变量或表达式,2.1.1 C+的I/O流实现输入/输出,8,2.1.1 C+的I/O流实现输入/输出,可以利用操纵符进行输入/输出格式控制,具体见第7章。 C+中新增加了一种换行控制符
4、endl,与C语言中常用的n等效,实现输出时的换行。 例如: couta=aendl; 和 couta=an;,9,2.1.3 名字空间,1、名字空间的定义 (1)定义形式: namespace 名字空间名称 ; (2)说明: 以关键字namespace定义名字空间,名字空间名称是合法的用户自定义标识符。 以一对大括号括起该名字空间的开始和结束处,右大括号后面不加分号。 在名字空间以外声明或定义的任何实体,都可以出现在名字空间内。,10,2.1.3 名字空间,2、名字空间中内容的使用 方法一:名字空间名称:局部内容名 其中的“:”称为域解析符或作用域运算符,用来指明该局部内容来自于哪一个名字空
5、间,从而避免命名冲突。 方法二:using namespace 名字空间名称 可以直接使用该名字空间中所有的内容, 方法三:using 名字空间名称:局部内容名 可以直接使用该名字空间中这一局部内容名,而该名字空间中的其余内容在使用时仍要附加名字空间名称和域解析符。,【例2.2】关于名字空间的主要用法示例 #include using namespace std; /*using声明使用一个完整的名字空间std,C+中提供的名字*/ /空间std涵盖了所有标准C+的定义和声明 namespace one /定义一个名字空间one,有M和inf const int M=200; int inf=
6、10; /后面不加分号 namespace two /定义一个名字空间two,有x和inf int x; int inf=-100 ; /后面不加分号,using namespace one ; /*using声明使用一个 完整的名字空间one*/ void main( ) using two:x ; /using声明仅使用two中的x x=-100 ; /直接访问,相当于two:x=-100; coutinfendl; /直接使用one中所有成员 coutMendl; two:inf*=2; /*使用名字空间名:局部内容名 操作未使用using声明的内容*/ couttwo:infendl;
7、 /*同样是two中的 内容,但是访问方式不一样*/ coutxendl ; /直接访问two中的x ,返回,13,例2.3:两种符号常量定义的区别示例 #include using namespace std; void main( ) int x=5; #define T1 x+x /用宏定义定义常量T1 #define T2 T1-T1 /用宏定义定义常量T2 cout“T1=”T1“ T2=”T2; ,2.2.1 使用const修饰符定义常量,运行结果:T1=10 T2=10,const int T1=x+x ; /用const定义定义常量T1,const int T2=T1-T1;
8、/用const定义定义常量T2,运行结果:T1=10 T2=0,14,在C+语言中,利用const关键字定义常量 const double PI=3.14159; 说明: 用const定义符号常量的基本形式为: const 常量类型 符号常量名=常量值; 缺省的“常量类型”为int型,符号常量定义的最后一定要有分号 定义的位置可以在函数体外或函数体内,只是作用域不同 符号常量用宏定义在C+语言中仍支持,但是建议使用更安全的const定义方式,2.2.1 使用const修饰符定义常量,15,2.2.2 const修饰符与指针的结合,1、指向常量的指针 定义形式:const 类型名 * 指针名;
9、例如:int x=5; const int *p; p= 含义:指针p本身是变量,指向整型常量 x=1;/正确 *p=1;/错误,【例2.4】指向常量的指针用法示例 #include using namespace std; void main( ) int x=5; int y=6; const int * p= ,程序的运行结果为: x=5 y=6 *p=5 x=10 y=6 *p=10 x=10 y=6 *p=6,const int x=5; /这样修改后程序还正确吗?,17,2、常指针 定义形式: 类型名* const 指针名=地址值; 例如:int x=5; int * const
10、p= 含义:指针p本身是常量,因此p第一次次获得地址值只能通过初始化方式 ,但是*p是变量,可以被改变 修改上面的例2.4,得到程序:,2.2.2 const修饰符与指针的结合,/修改例2.4,常指针示例 #include using namespace std; void main( ) int x=5; int y=6; int * const p= ,程序的运行结果为: x=5 y=6 *p=5 x=10 y=6 *p=10 x=20 y=6 *p=20,19,3、指向常量的常指针 定义形式: const 类型名 * const 指针名=地址值; 例如:int x=5; const in
11、t * const p= 含义:指针p本身是常量,p指向的内容即*p也是常量,因此p第一次获得地址值只能通过初始化方式,程序中对p和*p均不可修改。,2.2.2 const修饰符与指针的结合,/修改例2.4,指向常量的常指针示例 #include using namespace std; void main( ) int x=5; int y=6; const int * const p= ,程序的运行结果为: x=5 y=6 *p=5 x=10 y=6 *p=10 x=10 y=6 *p=10,返回,21,C+语言新增加了bool和string数据类型,在枚举类型、联合体类型、结构体类型的定
12、义和使用上也与在C语言中存在一些差别。 为了更方便地处理逻辑值,C+语言保持了C语言用0表示逻辑假,非0表示逻辑真的用法,新增加了数据类型bool,用常量true 表示逻辑真,用常量false表示逻辑假。所有的关系运算、逻辑运算都产生bool类型的结果值 可以使用C+标准库提供的boolalpha操纵符使逻辑真、逻辑假输出为true或false,可以用noboolalpha操纵符使输出恢复为1或0。,2.3.1 新增bool类型,【例2.5】布尔型变量使用示例。 #include using namespace std; void main( ) bool f=12; coutf boolal
13、phaf noboolalphafendl; ,程序的运行结果为: 1 true 1,23,C+语言新增加了string类型来代替C语言中以0结尾的char类型数组。使用string类型必须包含头文件string。 优点:有了string类型,程序员无需关心内存如何分配,也无需处理复杂的0结束字符,这些操作将由系统自动完成。 String类型提供的操作:赋值、读写、求串长、字符串联结、修改、比较、查找等,2.3.2 新增string类型,24,教材的例2.6在VC+6.0下运行演示 该例中注意以下几点: 定义一个string串变量时可以有多种初始化方式,如程序中s1、s2、s3、s4 可直接用
14、对string类型的字符串变量赋值 可用”+”实现串连接 可调用insert 、erase、substr、replace 、find等完成多种操作,2.3.2 新增string类型,25,C+语言的结构体类型与C语言结构体类型有两个区别: (1)在C+语言中定义结构体类型时,struct后面的标识符可以直接作为该结构体类型的类型名 ,例如: struct Point double x,y; ; Point p; /在C+语言中Point可作为类型 struct Point p; /在C语言中必须这样写,2.3.5 扩展了的结构体类型,26,C+语言中仍支持C语言中的类型转换形式,即:(目标类型
15、名)待转换源数据。 例如:将一个float型的值转换为int型结果,可以使用如下格式进行转换: float f=100.23; int x=(int)f; C+语言提供了另一种更为方便类似于函数调用的转换方式:目标类型名(待转换源数据) 上面的转换在C+语言中写成:x=int(f); 类型转换通过调用类型转换函数实现。,2.3.6 新增的强制类型转换方式,返回,27,在C+语言中,要求对于具有任何返回值类型的函数在调用之前都要作原型声明,以说明函数的返回值类型、函数名、形式参数类型与个数。 C+中函数原型声明的形式为: 函数返回值类型 函数名(形式参数表); 说明: 函数原型最简单的声明方法是
16、将函数定义的首部复制到调用点之前,然后在最后加一个分号,函数原型作为程序中的一条语句必须以分号结束。,2.4.1 函数原型,28,函数返回值类型建议都要给定,若一个函数没有返回值,则必须在原型声明中声明其返回值类型为void 函数原型参数表中必须指明形式参数的个数和类型,形式参数名可以省略 例如:float Fun(int a, float b); 与 float Fun(int , float ); 完全等效 如果原型声明时形式参数表为空,则该函数的参数表为void 先定义后被调用的函数以及main函数无需作原型声明,2.4.1 函数原型,29,C+语言提供了局部变量更加灵活的定义方式,在满
17、足先定义后使用的原则下,局部变量可以随用随定义 局部变量的定义和声明可以在程序块的任何位置出现,变量的作用域为从定义点到该变量所在的最小程序块末 变量定义位置的建议:若函数代码较长在最靠近使用变量的位置定义变量较为合理;若函数代码较短,将局部变量集中在函数开始处定义更好,2.4.2 局部变量随用随定义,30,在C语言中,一个全局变量在同名局部变量的作用域内是不可见的。 在C+语言中,在同名局部变量的作用域内,通过在同名变量前加上域解析符“:”可以对同名全局变量进行访问。 【例2.7】局部变量随用随定义及用域解析符扩大变量的作用域示例。,2.4.3域解析符:扩大变量的可见范围,#include
18、#include using namespace std; /使用C+的标准名字空间 int sum=5050; /定义全局变量sum void main( ) int arr3; int i; /定义变量i ,作用域不包括第1个for for (int i=0;iarri; /其作用域仅在本循环内 int sum=0 ; /*定义局部变量sum,与全局 sum同名,函数内默认的sum是该局部变量*/,for (i=0;i3; i+) /此处的i为函数开始处定义的i sum+=arri; for (i=0;i3 ;i+) /此处的i为函数开始处定义的i coutsetw(4)arri; cou
19、tendl; cout局部sum= ; /输出局部sum变量的值 coutsumendl; :sum+=sum; /*通过域解析符在同名局部变量作用域内对全局sum访问,赋值号右边的sum为同名局部变量*/ cout全局sum=; /输出全局sum变量的值 cout:sumendl; ,运行程序,从键盘上输入: 1 2 3, 程序的运行结果为: 1 2 3 局部sum=6 全局sum=5056,33,在C+语言中调用一个函数时,允许实在参数的个数形式参数个数。 原因:在C+语言中,在函数原型声明或函数定义首部为一个或多个形式参数指定默认参数值。调用该函数时,允许对具有默认参数值的形式参数不提供
20、实在参数而直接使用默认参数值,2.4.4 形式参数可带有默认值,【例2.8】形式参数带有默认值的函数原型声明、定义及多种调用方式示例。 #include using namespace std; void Fun(int i, int j=5, int k=10) ; /原型声明中形参j和k分 void main( ) /别指定了默认参数值5和10 Fun( 20 ) ; Fun( 20, 30 ) ; Fun( 20, 30, 40 ); void Fun(int i, int j ,int k) /原型中已指定了默认值,在 /函数定义的首部不能再指定 couti j kendl; ,20
21、5 10 20 30 10 20 30 40,35,默认参数值指定的顺序一定是从右到左依次,即具有默认值的参数从最右边开始 对上例,下面的原型声明均正确: void Fun(int i, int j, int k=10); void Fun(int i=1, int j=5, int k=10); 对上例,下面的原型声明均错误: void Fun(int i, int j=5, int k); void Fun(int i=1, int j, int k=10); void Fun(int i=1, int j, int k);,2.4.4 形式参数可带有默认值,36,定义方式: 在函数定义首
22、部前面加关键字“inline” 作用:将函数体代码插入到函数调用处 优点: 消除函数调用时系统开销,提高运行速度。 【例2.9】用内联函数取代带参数的宏定义示例,2.4.5 高效简洁的内联函数,37,关于内联函数,再作以下几点说明: 内联函数一般定义在被调用点之前 内联函数的代码一般都比较简短,功能也较简单,因为它是一种用空间换时间的措施。因此,在内联函数体内一般不能有循环语句和分支语句,递归也是不允许的 从第3章开始,在面向对象程序设计中,定义在类内的成员函数都将自动理解为内联函数,前面无需加“inline”关键字,2.4.5 高效简洁的内联函数,38,例如:求平方,同一程序中要求参数分别为
23、int、float和double型,在C语言中只能定义3个不同名的函数如下: int SquareOfInt( int x) ; /求整数的平方 float SquareOfFloat( float x) ; /求浮点数的平方 double SquareOfDouble( double x); /求双精度数的平方,2.4.6 函数重载,39,在C+语言中,对于功能完全相同或类似,只是在形式参数的个数、类型、顺序方面有区别的不同函数以相同的函数名来命名,该同名函数称为被重载(Overload) 编译器通过匹配实参与同名函数的形参判断调用的是哪一个同名函数 【例2.10】求平方问题的重载示例,2.
24、4.6 函数重载,#include using namespace std; int square(int x) /重载函数的第1个版本, int型参数 return x*x; float square(float x ) /重载函数的第2个版本 return x*x; double square(double x=1.5 )/重载函数的第3版本 return x*x; void main( ) coutsquare( )=square( )endl; coutsquare(10)=square(10)endl; cout“square(2.5f)=”square(2.5f)endl ; co
25、utsquare(1.1)=square(1.1)endl ; ,调用第3个重载的函数,调用第1个重载的函数,调用第2个重载的函数,程序的运行结果为: square( )=2.25 square(10)=100 square(2.5f)=6.25 square(1.1)=1.21,调用第3个重载的函数,41,说明: (1)重载函数必须具有相同的函数名,但是在形式参数的个数、类型、顺序的某一个或几个方面必须有所区别,返回值类型是否相同无关紧要,因其不在参数匹配检查之列 判断下列重载的正误: void Fun(int);与 void Fun( ); void Fun(int);与 void Fun
26、(double ); void Fun(int,double);与 void Fun(double ,int); void Fun(int);与 void Fun(double,char ); void Fun(int);与 int Fun(int);,2.4.6 函数重载,42,(2)二义性 新增: int square(int x,int y=100) return x*x+y*y; int square(int x) float square(float x ) double square(double x=1.5),2.4.6 函数重载,43,(3)在函数调用时,如果给出的实在参数和形
27、式参数类型不相符,C+编译器会自动进行类型转换。如果转换成功,则程序继续运行;否则,有可能产生不可识别的错误。 因此在调用时,最好保证实在参数的个数、类型、顺序与某一版本的重载函数的形式参数完全一致,避免不必要的错误。,2.4.6 函数重载,返回,44,引用(Reference) 变量的别名 作用:在不同的作用域内访问同一内存单元。 用途:用作函数参数 用作函数的返回值类型 格式: 数据类型 ,2.5.1 引用的概念及使用,45,说明: (1) “ int x=5,y=10; int ,【例2.11】引用的最基本用法示例,void main( ) print( ); r=y ; /相当于x=y
28、, y=100 ; print( ) ; ,程序的运行结果为: x=5 y=10 r=5 Address of x 00474DD0 Address of y 00474DD4 Address of r 00474DD0 x=10 y=100 r=10 Address of x 00474DD0 Address of y 00474DD4 Address of r 00474DD0,47,在C+语言中,引用最主要的用途是作为函数的形式参数,在函数被调用时引用成为实在参数变量在被调函数中的别名,从而可以通过对引用的访问和修改达到对实在参数变量进行操作的效果,为对实在参数变量的访问和修改提供了简单
29、方便的途径。 引用参数使得实在参数变量的作用域“扩大”到原先无法进入的被调函数中。,2.5.2 引用作为形式参数,48,总结: 引用参数与对应实参变量共享内存 与引用形式参数对应的实在参数只能是变量,而不能是常量或表达式 在无需改变对应实在参数变量值时,用引用参数仍然比用值形式参数更高效,因为无需另外分配空间和进行传值操作 ,此时可将引用参数前面加const限制来保护对应实参,2.5.2 引用作为形式参数,int Fun(const int ,void main( ) int a=1,b=2,c=3,d=0; couta=a b=b c=c d=dendl; d=Fun(a,b,c); cou
30、ta=a b=b c=c d=dendl; ,程序的运行结果是: a=1 b=2 c=3 d=0 a=1 b=7 c=3 d=7,【例2.13】3种不同的形式参数对实在参数的不同影响示例。,#include void swap( int *m, int *n) int temp; temp=*m; *m=*n; *n=temp; void main() int a=5, b=10; swap( ,大家知道两者的差别吗?,#include void swap( int ,与C语言中指针作函数参数的比较:,51,调用以引用作形式参数的函数和以指针作形式参数的函数时不同的内存占用情况,2.5.3 引
31、用与指针的区别,a,3,b,5,x,y,实参,形参,swap(a,b)调用以引用为形参的函数,实参,a,b,3,5, ptr=(int *)malloc(sizeof(int); /*申请1个int大小的动态内存空间,该空间中是随机数*/ ptr=(int *)malloc(10*sizeof(int); /*申请连续10个int大小的内存空间实现动态一维数组*/ ptr=(int *)calloc(10,sizeof(int); /*申请1个int大小的动态内存空间并将该空间值赋为10*/,2.6.1 用new申请动态内存空间,在C+语言中对应地用以下方法,ptr=new int ;,ptr
32、=new int 10;,ptr=new int (10);,56,在C语言中,用free(指针变量名)释放指针所指向的动态内存空间;在C+语言中,利用运算符delete更简单方便地实现动态内存空间的释放 使用delete运算符来释放动态内存空间的具体形式是: delete 指针变量名;/*释放单个空间,对应于new 类型名申请*/ delete 指针变量名;/*释放数组空间,对应于new 类型名 申请*/,2.6.2 用delete释放动态内存空间,57,C+动态内存空间管理特别注意: 在用new 或new 申请了动态内存空间后,一旦这部分动态内存空间使用结束,一定要及时用delete或de
33、lete释放空间,否则会产生内存垃圾 在使用new、delete时不要将它们与存储管理函数malloc、calloc、free混合使用,建议在C+程序中使用new、delete、new 、delete ,2.6.2 用delete释放动态内存空间,58,void通常表示无值,但是将void作为指针的类型时,它却表示不确定的类型 void型指针成为一种通用型指针,任何类型的指针均可直接赋值给void型指针变量,这一特性使void 型的指针在编写通用程序时很有用 注意:可以定义void类型的指针,但是不能定义void类型的变量 void类型的指针是通用指针,只是强调它可以直接接受任何类型指针变量的
34、赋值;但是,对于已经获得值的void类型指针变量,利用该指针处理所指向内存中的内容时,必须再进行显式类型转换,否则将会出错。,2.6.3 void类型的指针,【例2.14】void类型指针的各种用法示例,注意各行的注释 #include using namespace std; void main( ) /void vr; void *vp; char c=A; short int x=97; vp= ,程序的运行结果为: A -13247 97 a,返回,60,异常处理是C+语言的一种工具,使用这种工具可以对程序中某些事先可以预测的错误进行测试和处理 C+语言使用了throw和try-cat
35、ch语句支持异常处理 程序中的错误可分为两大类: 语法错误:包括编译错误和链接错误,这类错误在编译链接时根据出现的错误信息可以进行纠正。 运行错误:在编译链接通过后在运行时出现的错误,通常包括不可预料的逻辑错误和可预料的运行异常,2.7.1 异常和异常处理,61,C+语言中异常处理的机制由以下3步来实现。 (1)检查异常(使用try语句块) (2)抛出异常(使用throw语句块) (3)捕捉异常(使用catch语句块) 其中(1)(3)两步在上级函数中处理 第(2)步在可能出现异常的当前函数中处理 【例2.15】C+异常机制的处理过程示例,2.7.2 异常处理的实现,#include usin
36、g namespace std; int divide(int x,int y) if (y= =0) throw y; /如果分母为零,抛出异常 return x/y; void main( ) int a=10,b=5,c=0; try /检查是否出现异常 couta/b=divide(a,b)endl; coutb/a=divide(b,a)endl; couta/c=divide(a,c)endl; coutc/b=divide(c,b)endl; catch(int) /捕获异常并作出处理 coutexcept of divide zeroendl; coutcalculate fi
37、nishedendl; ,程序的运行结果是: a/b=2 b/a=0 except of divide zero calculate finished,说明: (1)throw语句的功能是抛出异常,其格式为: throw ;或throw ; 该语句写在可能出现异常的函数体内 (2)try-catch语句块的功能是用来检测、捕获并处理异常,格式为: try catch(或) try-catch语句块必须一起出现在调用可能出现异常的函数的上级函数,且try块在先catch块在后,try和catch块之间不能有任何其他语句。 允许只有try块而没有catch块,表示只检查异常而不处理异常;try块如果有,只能有一个,而对应的catch块可以有多个,表示可以与不同的异常信息相匹配。,64,(3)C+语言中异常处理的完整过程:程序顺序执行try块中的语句。如果在执行try块内
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 药品库存abc管理办法
- 董事、监事委派管理办法
- 虹口区厂房工程管理办法
- 融资租赁企业监督管理办法
- 衢江区小额工程管理办法
- 衡水公积金管理办法细则
- 裕安区扶贫项目管理办法
- 西安物业管理收费管理办法
- 视频监控室值守管理办法
- 评标专家评审期间管理暂行办法
- 施工安全生产管理制度范本
- 药店药品培训知识课件下载
- 贵州省黔西南布依族苗族自治州兴义市第八中学2025届高一物理第二学期期末学业质量监测试题含解析
- 初中语文新课程标准理论测试题及答案
- 2025年电信运营商数字内容业务发展机遇洞察-解码运营商在5G+AI时代的战略布局与增长引擎
- 外耳道肿物的护理查房
- 学堂在线 生活英语进阶 期末考试答案
- 2025年医生执业资格考试题及答案
- 2025年广东省中考生物试卷真题及答案详解(精校打印版)
- 招商部安全生产职责
- 设备操作维护培训
评论
0/150
提交评论