第2章C++对C的扩充.ppt

上传人:本田雅阁 文档编号:3423407 上传时间:2019-08-24 格式:PPT 页数:41 大小:161.04KB
返回 下载 相关 举报
第2章C++对C的扩充.ppt_第1页
第1页 / 共41页
第2章C++对C的扩充.ppt_第2页
第2页 / 共41页
第2章C++对C的扩充.ppt_第3页
第3页 / 共41页
第2章C++对C的扩充.ppt_第4页
第4页 / 共41页
第2章C++对C的扩充.ppt_第5页
第5页 / 共41页
点击查看更多>>
资源描述

《第2章C++对C的扩充.ppt》由会员分享,可在线阅读,更多相关《第2章C++对C的扩充.ppt(41页珍藏版)》请在三一文库上搜索。

1、第2章 C+对C的扩充,2.1 C+的特点 2.2 C+语言的文件扩展名 2.3 注释符 2.4 名字空间 2.5 C+语言的输入输出 2.6 变量的定义 2.7 强制类型转换,2.8 动态内存的分配与释放 2.9 作用域运算符: 2.10 引用 2.11 const修饰符 2.12 字符串 2.13 C+语言中函数的新特性,2.1 C+的特点 C+语言既保留了C语言的有效性、灵活性、便于移植等全部精华和特点,又添加了面向对象编程的支持。 用C+编写的程序可读性好,生成的代码质量高,运行效率仅比汇编语言慢10%20%。,2.2 C+语言的文件扩展名,为了使编译器能够区别是C语言还是C+语言,C

2、+语言体系规定用“.cpp”(意即C Plus-Plus)作为C+语言源文件的扩展名以区别于C语言用的“.C”文件扩展名。 与C+语言源文件相关的头文件扩展名一般仍用“.h”(有些操作系统也规定使用“.hpp”)。,2.3 注释符,1. 段注释: /*/ 2. 单行注释:/ 当只做单行注释时便可用“/”符号表示从此符号起至行尾均为行注释内容。 程序编译时将忽略所有的注释内容。,2.4 名字空间(名空间namespace),用花括号把文件的一部分括起来,并以关键字namespace开头给它起一个名字: namespace ns1 float a,b,c; fun1() ,花括号括起来的部分称声明

3、块。声明块中可以包括:类、变量(带有初始化)、函数(带有定义)等。在域外使用域内的成员时,需加上名字空间名作为前缀,后面加上域操作符“:” 。如:ns1:a,ns1:fun1() 。 最外层的名字空间域称为全局名字空间域(global namespace scope),即文件域。 名字空间域可分层嵌套,同样有分层屏蔽作用。如: namespace n1 namespace n2 / 名字空间嵌套 class matrix / 名字空间类成员matrix 访问matrix,可写: n1:n2:matrix,使用using声明可只写一次限定修饰名。using声明以关键字using开头,后面是被限定

4、修饰的名字空间成员名,如: using n1:n2:matrix;/ 名字空间类成员matrix的using声明 以后在程序中使用matrix时,就可以直接使用matrix,而不必使用限定修饰名。 使用using指示符可以一次性地使名字空间中所有成员都可以直接被使用,比using声明方便。using指示符以关键字using开头,后面是关键字namespace,然后是名字空间名。如: using namespace ns1;,标准C+库中的所有组件都是在一个被称为std的名字空间中声明和定义的。在采用标准C+的平台上使用标准C+库中的组件,只要写一个using指示符: using namespa

5、ce std; 就可以直接使用标准C+库中的所有成员。 注意:如果使用了名空间std,则在使用#include编译预处理命令包含头文件时,必须去掉头文件的扩展名.h,否则会出错。,#include using namespace std; 和 #include 是一样的,2.5 C+语言的输入输出,C+语言另外定义了一套保留字与运算符来替代C语言中对标准输入、输出函数的引用。 #include cout“输入内容”;/标准输入流对象(默认从键盘输入),【例2.1】C+的输入输出举例。 #include/ 使用名空间std,则必须去掉.h扩展名 using namespace std; void

6、 main() char name10; int age; coutname; coutage; cout“name is “nameendl; cout“age is “ageendl; ,2.6 变量的定义,C+允许变量的定义语句可以出现在程序的任何位置。 C+允许直接使用结构体名(联合名、枚举名)定义变量。,【例2.2】C+的变量定义举例。 #include using namespace std; void main() struct student int no; float math; ; int n; cinn; student wang; wang.no=n; cinwang.

7、math; coutwang.no“ “wang.mathendl; ,2.7 强制类型转换,格式: (数据类型)(表达式) 或: 数据类型(表达式) int b; float f; f=float(b);/此时变量b仍然为int类型 float(i)*f /*强制类型转换符优先级较高,先将变量i强制类型转换为float类型,然后与变量f运算*/,2.8 动态内存的分配与释放,1.new运算符做分配 指针变量 = new 数据类型; 2.delete运算符做释放 delete 指针变量;/*其中的指针变量保存着new动态分配的内存的首地址*/ 注意: (1) 用new获取的内存空间,必须用de

8、lete进行释放; (2) 对一个指针只能调用一次delete; (3) 用delete运算符作用的对象必须是用new分配的内存空间的首地址。,#include using namespace std; void main() int *p; p=new int; / 分配内存空间 *p=5; cout*p; delete p; / 释放内存空间 ,【例2.3】new与delete应用举例。,在用new分配内存的同时进行初始化。使用形式为: 指针变量 = new 数据类型(初始值); 例如上例中的: p=new int; *p=5; 也可写成: p=new int(5);,指针变量 = new

9、 数据类型数组大小; 此时指针变量指向第一个数组元素的地址。使用new分配数组时,不能提供初始值。使用new建立的数组变量也由delete释放。其形式为: delete 指针变量; 或 delete 指针变量; 同样,也可以用new来为多维数组分配空间,但是除第一维可以为变量外,其它维数都必须是常量。,用new建立数组类型的变量,注意在使用delete时,不用考虑数组的维数。 有时,并不能保证一定可以从堆内存中获得所需空间,当不能成功地分配到所需要的内存时,new返回0,即空指针。因此我们可以通过判断new的返回值是否为0,来得知系统中是否有足够的空闲内存来供程序使用。例如: int *p=

10、new int100; if(p=0) cout “cant allocate more memory,terminating. “endl; exit(1); 其中exit函数的作用是终止程序运行。,#include void main() int n;/定义数组元素的个数 int *p; coutn; if(p=new intn)=0)/分配内存空间 cout “cant allocate more memory,terminating.“ endl; exit(1); for( int i=0;in;i+) pi= i *2; cout“Now output the array:“end

11、l; for( i=0;in;i+) coutpi“ “; coutendl; delete p;/释放内存空间 ,【例2.4】从堆内存中获取一个整型数组,赋值后并打印出来。,补充:复制初始化和直接初始化。,int n(50);/直接初始化 int m=20;/复制初始化,注意:初始化不是赋值,2.9 作用域运算符:,通常情况下,如果全局变量与局部变量同名,那么局部变量在其作用域内具有较高的优先权。C+中提供的作用域运算符:,它能指定所需要的作用域。 注意:不能用:访问函数中的局部变量。在C+语言中作用域运算符:还用来限定类的成员。,#include using namespace std;

12、float a=2.4; / 全局变量 void main() int a=8; / 局部变量 coutaendl; cout:aendl; /:a表示全局变量a ,2.10 引用,引用,用于在程序的不同部分使用两个以上的变量名指向同一地址(内存空间),使得对其中任一个变量的操作实际上都是对同一地址单元进行的。被声明为引用类型的变量名则是实际变量名的别名。 引用运算符为&,声明引用的一般形式为: 数据类型 &引用变量名 = 变量名; 或 数据类型& 引用变量名 = 变量名; 或 数据类型 & 引用变量名 = 变量名; 对引用进行操作,实际上就是对被引用的变量进行操作 引用不是值,不占存储空间

13、引用一旦被初始化,就不能再重新赋值,【例2.5】引用举例。 #include void main() int num=50;int ,11点说明: 在一行上声明多个引用型变量(函数)名时,要在每个变量(函数)名前都冠以“/对,(4)由于引用不是变量,所以,不能说明引用的引用,也不能说明数组元素的类型为引用数组,或指向引用的指针(引用不占内存空间)。例如: int / a指向变量b (5)引用与指针不同 指针的内容或值是某一变量的内存单元地址,而引用则与初始化它的变量具有相同的内存单元地址。 指针是个变量,可以把它再赋值成其它的地址,然而,建立引用时必须进行初始化并且决不会再指向其它不同的变量。

14、,(6)引用运算符和地址运算符不同。例如: int num=50; int /num被修改为100 (8)常把函数的参数说明成引用以建立函数参数的引用传递方式。 【例2.7】引用作为函数参数实现数值交换,(9) 有空指针,无空引用 (10)引用不能用数据类型来初始化。如: int &ref=int;/ error (11)返回引用的函数调用可作为左值 若一个函数返回了引用,那么该函数的调用也可以被赋值。 返回值不能是函数的局部变量的引用。 引用返回值只用在需对函数的返回值重新赋值的时候。 【例2.8】统计学生中A类学生与B类学生各为多少个。A类学生的标准是平均分在80分以上,其余都是B类学生。

15、 *【例2.9】返回的局部作用域内的变量,函数作为左值。,2.11 const修饰符,#define PI 3.1415926 const float PI=3.1415926; const常量有类型 有地址 可以用指针指向这个值,但不能修改它 C+建议用const取代#define,注意:,(1)使用const修饰符定义常量时,必须初始化 (2)常量一旦被定义,在程序中任何地方都不能再更改。 (3)如果用const定义的是一个整型常量,int可以省略。 (4)与#define定义的常量有所不同,const定义的常量可以有自己的数据类型,这样C+编译程序可以进行更加严格的类型检查,具有良好的编

16、译时的检测性。 (5)函数参数也可以用const说明,用于保证实参在该函数内部不被改动。 例如,通过函数max求出整型数组a100中的最大值,函数原型应该是: int max(const int* pa); 这样做的目的是确保原数组的数据不被破坏,即在函数中对数组元素的操作只许读,不许写。,const与指针一起使用的组合情况:,(a)指向常量的指针 指向常量的指针是指一个指向常量的指针变量。 const char* pc=“abcd“; 声明指向常量的指针变量pc,它指向一个字符串常量 由于使用了const,不允许改变指针所指的常量,因此以下语句是错误的: pc3=x; 但是由于pc是一个指向

17、常量的普通指针变量,不是常指针,因此可以改变pc的值。例如以下语句是允许的: pc=“jkkk”;/另外申请了一块内存空间,(b) 常指针 常指针是指指针本身,而不是它指向的对象为常量。例如: char* const pc=“abcd“; / 常指针 这个语句的含义为:声明一个名为pc的指针变量,该指针是指向字符型数据的常指针,用“abcd”的地址初始化该常指针。创建一个常指针,就是创建不能移动的固定指针,但是它所指的数据可以改变。例如: pc3=x; / 合法(?) pc=“jkkk“; / 不合法,(c) 指向常量的常指针 指针本身不能改变,它所指向的值也不能改变。要声明一个指向常量的常指

18、针,二者都要声明为const。例如: const char* const pc=“abcd“; / 指向常量的常指针 这个语句的含义为:声明一个名为pc的指针变量,它是一个指向字符型常量的常指针,用“abcd”的地址初始化该指针。以下两个语句都是错误的: pc3=x; / 错误,不能改变指针所指的值 pc=“dfasdfa“; / 错误,不能改变指针本身,2.12 字符串,在C+中提供了一种既方便又好用的string类型。例如:,#include #include using namespace std;/* 使用字符串string类型的程序应包含头文件,而且不能写成#include */ v

19、oid main() string s,t; couts; /*由键盘输入一行文本,并把它赋给sring类型的变量s,使用此方式输入的字符串中不能包含空格字符*/ t=“I like programming!“; cout“字符串的输出:“endlsendltendl; couts.append(“ OK!“)endl;/*append为string类的成员函数*/ ,2.13 C+语言中函数的新特性,2.13.1 函数原型(Function Prototype) 2.13.2 内联(inline)函数 2.13.3 带缺省参数的函数 2.13.4 函数重载(overload) 2.13.5

20、函数模板(function template),C+要求为每一个函数建立原型,用以说明: 1函数的名称 2参数个数及类型 3函数返回值的类型。 养成将声明与定义分别编写的编程习惯。 函数原型(声明)与函数的定义要在上述3点上保持一致。 写函数原型时,可以省略形参的名字,2.13.1 函数原型(Function Prototype),2.13.2内联(inline)函数,在执行程序过程中如果要进行函数调用,需要时间和空间的开销,使得程序执行效率降低。C+引入了内联函数机制,通过在函数声明前加上关键字:inline。 编译器会将编译后的全部内联函数的目标机器码复制到程序内所有的引用位置并把往返传送

21、的数据也都融合进引用位置的计算当中。 使用内联函数是一种用空间换时间的措施,若内联函数较长,且调用太频繁时,程序将加长很多。因此,通常只有较短的函数才定义为内联函数,对于较长的函数最好作为一般函数处理。,一般情况下,我们对内联函数做如下的限制: (1) 不能有递归 (2) 不能包含静态数据 (3) 不能包含循环 (4) 不能包含switch和goto语句 (5) 不能包含数组 若一个内联函数定义不满足以上限制,则编译系统把它当作普通函数对待。 【例2.11】内联函数的使用。,2.13.3带缺省参数的函数,在函数说明中为形参指定一个缺省值,则称此函数为带缺省参数的函数。当函数调用发生后,在形参表

22、中等号后的各“缺省值”将起实参的传递作用。 如果函数有多个缺省参数,则缺省参数必须是从右向左定义,并且在一个缺省参数的右边不能有未指定缺省值的参数。 void fun(int a=3,int b=6,int c,int d);/错 void fun(int a=65,int b=3,int c,int d=3);/错 void fun(int a,int b,int c=65,int d=3);/对 函数调用时,参数不带缺省值。,例: #include void fun(int a,int b,int c=65,int d=3); void main() fun(1,2); fun(1,2,3

23、); fun(1,2,3,4);/分别是什么效果 void fun(int a,int b,int c,int d)/函数定义时参数不带缺省值 coutaendlbendlcendldendlendl; ,2.13.4函数重载(overload),C+编译系统允许为两个或两个以上的函数取相同的函数名,但是形参的个数或者形参的类型不应相同(不涉及函数的返回值类型),编译系统会根据实参和形参的类型及个数的最佳匹配,自动确定调用哪一个函数,这就是所谓的函数重载。 函数重载无需特别声明,只要所定义的函数与已经定义的同名函数形参形式不完全相同,C+编译器就认为是函数的重载。例如: void f1(int

24、 ,double); void f1(int ,int); void f1(int ,int ,int); 【例2.12】重载函数应用举例,注意: 不可以定义两个具有相同名称、相同参数类型和相同参数个数,只是函数返回值不同的函数。 int func(int x); float func(int x);/ambiguous 如果某个函数参数有缺省值,必须保证其参数缺省后调用形式不与其它函数混淆。 int f(int a, float b); void f(int a, float b, int c=0); 函数调用语句: f(10, 2.0); /ambiguous 具有二义性,既可以调用第一个

25、函数,也可以调用第二个函数,编译器不能根据参数的形式确定到底调用哪一个。,2.13.5函数模板(function template),1、模板分为函数模板和类模板。 2、函数模板的一般说明形式如下: template (模板函数形参表) / 函数定义体 或: template (模板函数形参表);/声明 template (模板函数形参表)/定义 / 函数定义体 ,#include /【例2.13】 template T min(T a,int n);/声明 void main( ) int a=1,3,0,2,7,6,4,5,2; double b=1.2,-3.4,6.8,9.8; cou

26、t T min(T a,int n)/定义 int i; T minv=a0; for(i=1;iai) minv=ai; return minv; ,3、如果类型形参多于一个,则每个类型形参都要使用class或typename。如: template 4、模板函数 当编译系统发现有一个函数调用:;和函数模板一致时,将根据中的类型生成一个重载函数,即模板函数。该模板函数的定义体与函数模板的函数定义体相同,而的类型则以的实际类型为依据。 5、虽然模板参数T可以实例化成各种类型(包括结构体、类),但是采用模板参数T的各参数之间必须保持完全一致的类型。模板类型并不具有隐式的类型转换,例如在int与c

27、har之间、float与int之间、float与double之间等的隐式类型转换。,6.函数模板与重载函数 当模板函数与重载函数同时出现在一个程序体内时,C+编译器的求解次序是: 1.调用重载函数 2.如果不匹配,则调用模板函数 3.如果还不匹配则进行强制类型转换调用重载函数 4.报错 【例2.14】模板函数与重载函数。,上机练习: P36 1、2 所有上课的例子 研究思考: 1、为什么 #include using namespace std;和 #include 是一样的 为什么 #include using namespace std;和 #include 不一样 2、如果函数有多个缺省参数,则缺省参数必须从右向左定义,并且在一个缺省参数的右边不能有未指定缺省值的参数。为什么?编写程序验证你的猜测,并进一步研究函数调用时参数匹配的过程。 3、编写一个程序验证 当模板函数与重载函数同时出现在一个程序体内时,C+编译器的求解次序是: 1.调用重载函数 2.如果不匹配,则调用模板函数 3.如果还不匹配则进行强制类型转换调用重载函数,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1