1、1,主讲:杨晓花 计算机工程系,C+程序设计,2,第2章 C+概述,本章重点:C+在非面向对象方面的特性,包括:新的I/O流、C+中的局部变量说明、const修饰符、内置函数、函数原型、带有缺省参数的函数、函数重载、new和delete运算符、引用 内容:2.1 C+的起源和特点2.2 C+源程序的构成2.3 C+在非面向对象方面的一些特性 本章小结 测试题,Home,3,2.1 C+的起源和特点,一、C+的起源 C+是美国贝尔实验室在C语言的基础上,增加了面向对象的特征,于1980年开发出来的一种过程性与对象性结合的程序语言。最初把它称为“带类的C”,83年后才取名为C+。 C语言已经被公认
2、为是非常好的一种中级语言,但它也有一些局限: 1.C的类型检查机制相对较弱,这使得程序中的一些错误不能在编译阶段由编译器检查出来。如:float x; scanf(“%d”,Back,Next,4,2.C语言本身几乎没有支持代码重用的语言结构。如:求一个数的绝对值,对于int型数据:int abs(int x);而对于float型数据则写成:float fabs(flaot x); 3.C语言不适合开发大型程序,当程序达到一定规模时,程序员很难控制程序的复杂性。 C+正是为了解决上述问题而设计的。C+继承了C的原有精髓(如高效率、灵活性),扩充增加了对开发大型软件颇为有效的面向对象的机制等等,
3、成为一种既可用于表现过程模型,又可用于表现对象模型的优秀的程序设计语言之一。,Back,Previous,Next,5,二、C+的特点 保持与C语言的兼容。 可读性更好。 代码质量高,仅比汇编语言慢10%-20%。 可重用性、可扩充性、可维护性、可靠性都有很大提高。 支持面向对象的机制。,Back,Previous,6,2.2 C+源程序的构成,一、C+程序的一般格式 例2.1:求两个数中的最大值的C和C+程序 C程序:MyMax.cC+程序:MyMax.cpp 练习:将C语言程序改写为C+程序,Back,Next,7,二、C+程序的结构特点 C+与C相同之处: 程序通常由一组函数组成,函数是
4、构成C+程序的基本单位。main为主函数,程序总是从它开始运行,与其所处的位置无关。 函数由函数的说明部分和函数体两部分组成。 每个语句和数据定义必须以分号结束。一行内可写多条语句,一个语句也可写成许多行。 不同: C源程序文件扩展名为.C,而C+为.CPP 对于一般的C+编译器,当给定扩展名为.c时,启动C的编译器;而当给定扩展名为.cpp时则启动C+的编译器。,Back,Previous,8,2.3 C+在非面向对象方面的一些特性,注释行 新的I/O流 灵活的局部变量说明 结构、联合和枚举名可直接作为类型名 const修饰符 内置函数 函数原型 带有缺省参数的函数 函数重载 全局变量作用域
5、运算符“:” 无名联合 强制类型转换 new和delete运算符 引用 命名空间namespace,Back,9,一、注释行 C语言注释方式:/* */ /* This is a C+ program. */ /* This isa C+ program. */ C+的注释方式:/ x=x+2; /使x加2 /下列函数求两个数中的最大值int max(int x,int y) 两种注释方式在C+中可以混合使用注意:新版的C编译器也支持“/”的单行注释。,Back,10,二、新的I/O流 1 使用cin和cout分别实现输入和输出操作时,在程序中必须嵌入头文件iostream.h。例2.2 2
6、在C+程序中仍然可以沿用传统的stdio函数库中的I/O函数。 3 使用cin可以连续输入多个数据,cout可以连续输出多个数据。C的输入输出 C+的输入输出 4 用cin或cout时,使用了系统缺省的格式。实际上我们可以对其进行控制。例2.3 5 在C+中可以使用endl来代替“n”实现输出换行。C+的换行控制,Back,11,三、灵活的局部变量说明 C+中允许在代码块中的任何地方说明局部变量: 它所说明的变量从其说明地点到该变量所在的最小分程序末的范围内有效(或从其说明地点开始有效)。C+局部变量的使用 通常认为: 在大函数中,在最靠近使用变量的位置说明变量较为合理; 在较短的函数中,把局
7、部变量集中在函数开始处说明比较好。,Back,12,四、结构、联合和枚举名可直接作为类型名 在C+中,结构名、联合名(共用体名)、枚举名都是类型名。如: enum boolFALSE,TRUE; struct stringchar *prt;int length; ; 在C中: enum bool done; struct string str; 在C+中: bool done; string str;,Back,13,五、const修饰符 在C中,习惯使用#define来定义常量,例如:#define LIMIT 100; C+提供一种更灵活、更安全的方式来定义常量,即const修饰符。一般
8、的语法格式:const 类型名 常量标识符=常量表达式;对于上例,用const定义为:const int LIMIT=100;这个常量LIMIT是类型化的,它有地址,可以用指针指向这个值,但不能修改它。 const也可以与指针一起使用,它们的组合有三种:,Back,Next,14,指向常量的指针变量: 如:const char *name=“chen”;以下语句:name3=a; /错误name=“zhang”; /正确,“chen”,name,变量,常量,Back,Next,Previous,“zhang”,常量,注意:char *name=“chen”;该语句仍然表示name为指向常量的指
9、针。,15,常(量)指针: 如:char ptr5 = “chen”; char * const name = ptr ;以下语句:ptr2=a; name=“zhang”; name2=a;,“chen”,name,常量,变量,Back,Next,Previous,ptr,/正确,/正确,/错误,“chan”,16,指向常量的常(量)指针: 如: const char * const name=“chen”;以下语句:name3=a; /错误name=“zhang”; /错误,“chen”,name,常量,常量,Back,Previous,17,六、内置函数 在函数说明前冠以关键字“inli
10、ne”,则该函数就被声明为内置函数。例2.6 内置函数 每当程序中出现对该函数的调用时,C+编译器使用内置函数体内的代码替代函数调用表达式,这样能加快代码的执行,减少调用开销。 使用内置函数替代宏定义,可以消除宏定义的不安全性。内置函数具有宏定义的所有优点而没有缺点。例2.7使用宏定义 例2.8使用内置函数 练习:写出程序的运行结果。然后将其改写为内置函数,再次写出运行结果。,Back,18,七、函数原型 除主函数外: C+要求为每一个函数建立原型。 函数原型的语法格式:函数类型 函数名(参数表);函数类型 函数名(类型表); 例2.9 说明: 如果一个函数没有返回值,则必须在函数原型中使用v
11、oid类型符。 如果函数原型中未注明参数,C+假定该函数的参数表为空(void)。如f();和f(void);是等价的。,Back,19,八、带有缺省参数的函数 C+在说明函数原型时,可为一个或多个参数指定缺省参数值,以后调用此函数,若省略其中某一参数,C+自动地以缺省值作为相应参数的值。例如函数原型说明为:int special(int x=5,float y=5.3);当进行函数调用时,可以有以下几种形式:1) special(100,79.8); / x=100,y=79.82) special(25); / x=25,y=5.33) special(); / x=5,y=5.3 说明:
12、 缺省参数都必须出现在不取缺省值的参数右边。如:int fun(int i,int j=5,int k);的说明错误。 2.在函数调用时,若某个参数省略,则其后的参数皆应省略而采用缺省值。 练习1 练习 2,Back,答案1,答案2,20,九、函数重载 在传统的C语言中,函数名必须是唯一的,也就是说不允许出现同名的函数。当要求编写求整数、浮点数和双精度的平方数的函数时,若用C来实现必须编写三个函数: iSquare(int x) fSquare(float x) dSquare(double x) 在C+中用户可以重载函数,即只要函数参数的类型不同,或者参数的个数不同,或者二者兼而有之,两个或
13、两个以上的函数可以使用相同的函数名。 当两个或者两个以上的函数共用一个函数名时,称为函数的重载。 例2.10 练习1 练习2 例2.11,Back,Next,21,说明: 重载函数应在参数个数或参数类型上有所不同,否则编译程序将无法确定调用哪一个重载版本,即使返回类型不同也不能区分。例如:int mul(int x,int y);double mul(int x,int y); / 错误 一般而言,重载函数应执行相同的功能,例如abs()函数一般用来返回一个数的绝对值,如果重载abs()函数,让它返回一个数的平方根,则是不可取的。,Back,Next,Previous,22,使用函数重载与默认
14、参数时应注意: 默认参数可将一系列简单的重载函数合成一个。如有三个重载函数:void func(int x,int y) coutx,yendl;void func(int x) func(x,10); void func() func(5,10);可以用下面的默认参数函数来代替:void func(int x=5,int y=10) coutx,yendl; 如果一组重载函数(可能带有默认参数)都允许相同实参个数的调用,将会引起调用的二义性。如有:void func(int x); /1void func(int x,int y=4); /2void func(int x=3,int y=4
15、); /3调用时: func(7); /错误,调用哪一个?func(20,30); /错误,调用后两个中的哪一个?,Back,Previous,23,十、全局变量作用域运算符“:” 通常情况下,如果有两个同名变量,一个是全局的,另一个是局部的,那么局部变量在其作用域内具有较高的优先权。例2.12如果希望在局部变量的作用域内使用同名的全局变量,可以在该变量前加上“:”,此时:avar代表全局变量avar,“:”称为作用域运算符。例2.13 思考:1.若将句1改为:aver=20,结果如何?2.若将句1,2都改为:aver,结果为多少?,Back,24,十一、无名联合无名联合是C+中的一种特殊联合
16、,它在关键字union后面没有给出联合名,它可使一组数据项共享同一内存地址。如:union int x; float y;其中变量x和y具有相同的存储地址。无名联合可通过使用其中数据项名直接存取,例如可直接使用上面的变量x或y,如下: union int x; float y;x=10; y=20; cout“x is “xendl; cout“y is “yendl;,Back,x is 1101004801y is 20,25,十二、强制类型转换 C中使用形如 (int)x的形式。 C+中还允许另一种函数调用方法形式,如int(x)。 以上两种方法C+都能接受,但推荐使用后一种方法。 例,
17、Back,26,十三、new和delete运算符 在C中动态内存分配是靠malloc()和free()两个函数完成的。 在C+中动态内存分配有更好、更简单的方法:(1)分配内存:p=new 数据类型;(2)释放内存:delete p; 说明: new在为简单变量分配内存的同时,可以进行初始化。如: int *p; p=new int(90); 例2.15 使用new可以为数组动态分配内存。如: int *p=new int10; 释放动态分配的数组内存区时,使用如下的格式: delete p; 例编程练习:将输入数据中高于平均数的数据输出。答案 使用new动态分配内存时,如果没有足够的内存时,
18、将返回空指针(NULL)。 例2.16,Back,27,十四、引用引用就是给变量一个别名,使指针运算更加方便。 引用的定义 类型名 ,(b),(c),(b),Back,Next,28,引用实际上是一种隐式指针。 int i=15;int *iptr= 相同,(rptr),Back,Next,Previous,29,引用作参数 引用作参数是引用的重要用途。如:int func(int ,Back,Next,Previous,10,10,20,30,例2.20:使用引用void swap(int 通过引用参数产生的效果同按地址传递是一样的,但其语法更清楚简单,因为在调用函数的所有参数前不需要间接引
19、用运算符*,原函数中传送的参数也不必是引用变量。 C+主张用引用传递取代地址传递的方式,因为引用语法容易且不易出错。,(m) (n),10,20,10,Back,Next,Previous,31,函数返回值为引用 为了将该函数用在赋值运算符的左边,可将函数的返回值说明为引用。 例2.21 #include int a=1,3,5,7,9;int ,25,Back,Next,Previous,32,4.引用举例(例2.22),#include int ,(num1) (num2),45 78,0,Back,Previous,33,十五、命名空间namespace,和是不一样,前者没有后缀,实际上
20、,二者的文件代码是不一样的。 后缀为.h的头文件是早些时候的C+实现,其将标准库(现在称伪标准库)功能定义在全局空间里,声明在带.h后缀的头文件里。 c+标准为了和C区别开,也为了正确使用命名空间,规定头文件不使用后缀.h。,34,十五、命名空间namespace,当使用时,相当于在c中调用库函数,使用的是全局命名空间,也就是早期的c+实现。当使用的时候,该头文件没有定义全局命名空间,必须使用namespace std;这样才能正确使用cout。 所谓namespace,是指标识符的各种可见范围。C标准程序库中的所有标识符都被定义于一个名为std的namespace中。,35,十五、命名空间n
21、amespace,由于namespace的概念,使用C标准程序库的任何标 识符时,可以有三种方法:1、直接指定标识符。std:cout 3.4 std:endl; 例2.232、使用using关键字。 using std:cout; using std:endl; 以上程序可以写成 cout 3.4 endl; 例2.24,36,十五、命名空间namespace,3、最方便的就是使用using namespace std;例如:#include using namespace std; 这样命名空间std内定义的所有标识符都有效(曝光)。就好像它们被声明为全局变量一样。那么以上语句可以如下写:
22、 cout 3.4 endl; 例2.25,37,十五、命名空间namespace,无数原有的C+代码都依赖于使用了多年的伪标准库中的功能,他们都是在全局空间下的。 所以就有了和等等这样的头文件,一个是为了兼容以前的C+代码,一个是为了支持新的标准。使用自定义命名空间,Back,例2.26,38,第2章小结,本章主要介绍了C+在非面向对象方面的一些重要特性: 注释行;新的I/O流;灵活的局部变量说明;结构、联合和枚举名可直接作为类型名;const修饰符;内置函数;函数原型;带有缺省参数的函数;函数重载;全局变量作用域运算符“:”;无名联合;强制类型转换;new和delete运算符;引用;名字空
23、间namespace。 这些新特性使C+比C更简洁或更安全,使得C+更好用。,Back,39,第2章测试题,单选题: 1、在C+中,单行注释语句通常使用_。A) /B) /*/C) note D) & ,Next,Back,40,第2章测试题,2、在C+中的开头必须使用#include 命令,以设置C+风格的I/O环境。A) stdio.hB) math.hC) string.hD) iostream.h,Next,Previous,Back,41,第2章测试题,3、C+中换行可以使用“n”转义字符,也可以使用换行控制符_。A) endlB) endlineC) endD) enter,Nex
24、t,Previous,Back,42,第2章测试题,4、若有: int a=5; char x=65; 则: coutax; 语句在屏幕上输出的结果是_。A) 565B) 5 65C) 5AD) 5 A,Next,Previous,Back,43,第2章测试题,5、若有: int x=36; 希望用八进制输出x的值,则输出语句应写成:_。A) coutx;B) coutdecx;C) couthexx;D) coutoctx;,Next,Previous,Back,44,第2章测试题,6、若有: enum BOOLFALSE,TRUE; 要把stop定义为该枚举类型的变量,应写成:_。A) e
25、num BOOL stop;B) BOOL stop;C) stop BOOL;D) 无法定义,Next,Previous,Back,45,第2章测试题,7、若有: struct Stringchar *ptr; int length; 要把str定义为该结构体类型的变量,应写成:_。A) ptr str;B) String ptr;C) String str;D) struct String str;,Next,Previous,Back,46,第2章测试题,8、若用LIMIT符号表示100这个整型常量,不正确的是_。A) #define LIMIT 100B) const int LIMI
26、T=100;C) const LIMIT=100;D) int LIMIT=100;,Next,Previous,Back,47,第2章测试题,9、在C语言中定义符号常量使用: #define PI 3.1415926在C+中更好的定义方法为:_。A) inline PI=3.1415926;B) const PI 3.1415926;C) const double PI 3.1415926;D) const double PI=3.1415926;,Next,Previous,Back,48,第2章测试题,10、关于内置函数不正确的说法是_。A) 消除宏定义的不安全性B) 加快代码的执行C)
27、 提高代码的可重用性D) 减少调用开销,Next,Previous,Back,49,第2章测试题,11、有函数原型:int special(int x=5,float y=5.3); 不合法的函数调用为_。A) special()B) special(10)C) spacial(,8.5)D) special(10,8.5),Next,Previous,Back,50,第2章测试题,12、错误的函数声明格式是_。A) int fun(int a,int b,int c);B) int fun(int a,int b,int c=10);C) int fun(int a,int b=5,int
28、c=10);D) int fun(int a,int b=5,int c);,Next,Previous,Back,51,第2章测试题,13、有int x=10;float y; 把x强制转换后送给y,在C+中应写成:_。A) y=float x;B) y=(float)x;C) y=float(x);D) y=(float)(x);,Next,Previous,Back,52,第2章测试题,14、有double *p;为p开辟一个动态内存空间,应使用:_。A) p=new double;B) *p=new double;C) p=(double *)new;D) *p=(double)new
29、;,Next,Previous,Back,53,第2章测试题,15、有int *p;为p开辟一个动态的内存空间,并初始化为20,应写成:_。A) p=new int 20;B) p=new int (20);C) p=new int 20;D) p=new int=20;,Next,Previous,Back,54,第2章测试题,16、有float *p;为了在动态的内存空间分配具有5个元素的float类型的数组,并将首地址赋给指针p,应写成:_。A) p=new float 5;B) p=new float (5);C) p=new float 5;D) p=new 5 float;,Nex
30、t,Previous,Back,55,第2章测试题,17、有int *p=new int;若将p所指向的动态内存单元释放,应写成:_。A) delete p;B) p=delete;C) delete int p;D) delete *p;,Next,Previous,Back,56,第2章测试题,18、有char *arr=new char80;若将arr所指向的动态数组释放,应写成:_。A) delete arr;B) delete arr;C) delete arr;D) delete arr5;,Next,Previous,Back,57,第2章测试题,判断题: 1、C+是C的一个子集
31、,它几乎保留了C的所有特征。 2、“/”注释方式特别适合于单行或行尾注释,而“/*/”注释方式特别适合于多行注释。 3、cin是标准的输入流,在程序中用于代表标准输入设备,通常指键盘。 4、cout是标准的输出流,在程序中用于代表标准的输出设备,通常指打印机。,Next,Previous,Back,58,第2章测试题,5、C+允许在执行了一些代码后再对局部变量说明。 6、在函数说明前面冠以关键字“inline”,该函数就被声明为内置函数了。 7、函数声明:void func(); 在C和C+中是相同的含义。 8、已经有函数定义:int cub(int x)return x*x*x; 若求一个d
32、ouble类型的立方,其函数名不能再是cub。,Next,Previous,Back,59,第2章测试题,9、已经有函数定义:int cub(int x)return x*x*x; 若要求一个double类型的立方,cub函数可重载为:double cub(double x)return x*x*x; 10、有float x;若将其强制转换为int类型后存入y中,可以写成y=(int)x; 也可以写成y=int(x); 11、有long *p;若p=new long;则语句delete p;是将p所占的内存单元释放掉。 12、由于在C+中,变量的说明可以出现在语句后。则:int n; cinn
33、; int an;是可以执行的,其作用是说明一个整型数组a,共有n个元素。,Next,Previous,Back,(所占改为指向的),60,第2章测试题,13、使用new操作符分配动态内存时,若没有足够的内存,new将返回NULL。 14、有int a; int b=a; a=10; b=20; 则couta,b;结果为“20,20”。,Next,Previous,Back,61,第2章测试题,程序填空 1、求输入两个整数的平均值。(1)double v; (2)double 2、求输入的两个实数之和。(1)return 0; (2)return c; 3、求输入的两数中的最大值。(1)voi
34、d main() (2)cinab; 4、求圆柱体的体积。(1)cinradius; (2)cinheigh;,Next,Previous,Back,62,第2章测试题,5、求圆柱体的表面积。(1)double height; (2)double area; 6、请重载求符号Sgn函数。(1) Sgn(float x) (2)Sgn(double x) 7、请重载mul函数,完成对给定的参数的乘积。(1) int mul(int a,int b,int c)(2) int mul(int a,int b,int c,int d) 8、请重载Power函数,完成求x的n次方。(1) float
35、Power(float x,int n)(2) double Power(double x,int n),Next,Previous,Back,63,第2章测试题,9、请重载Add函数,完成两个数相加。(1) float Add(float x,float y)(2) double Add(double x, double y) 10、请重载Sub函数,完成两个数相减。(1) int Sub(int x,int y)(2) float Sub(float x,float y),Next,Previous,Back,64,第2章测试题,修改程序 1、将程序中的circle函数修改为内置函数。将第
36、2行改为:inline float circle(float r) 2、求数组中的最高分、最低分和平均分,请修改程序。将第2行改为:double Average(int *p,int n,int 4、使用函数求两个数的和、差和积。请修改程序使之正确。将第2行改为: int mul(int x,int y,int &sum,int &sub),Next,Previous,Back,65,第2章测试题,5、下列程序有问题,请修改正确。在第1行后面插入:void write(char *s); 6、通过函数求某数的平方和立方。将第2行改为:int Cub(int x,int 8、通过函数求两个数的最大值和最小值。将第2行改为:void MaxAndMin(int x,int y,int &Max,int &Min),Back,Next,Previous,66,第2章测试题,9、请把求三角形面积的函数声明为内置函数。在第2行后面插入:inline double Area(int a,int b,int c); 10、通过函数求两个数的最大值和最小值。将第2行改为:int MaxAndMin(int x,int y,int &Min),Previous,Back,