《面向对象程序设计》课件第2章 C++对C的扩充.pptx
《《面向对象程序设计》课件第2章 C++对C的扩充.pptx》由会员分享,可在线阅读,更多相关《《面向对象程序设计》课件第2章 C++对C的扩充.pptx(42页珍藏版)》请在文库网上搜索。
1、 第第第第2 2章章章章 C+C+对对对对C C的扩充的扩充的扩充的扩充2.42.4 命名空间命名空间 2.82.8 动态内存的分配动态内存的分配2.102.10 引用引用2.112.11 const 修饰符修饰符2.132.13 C+中函数的新特性中函数的新特性2.4 2.4 命名空间命名空间 2.4.1 2.4.1 为什么要引入为什么要引入命名空间命名空间 命名空间是随标准命名空间是随标准C+而引入的,用来防止全而引入的,用来防止全局空间内的命名冲突,即重名问题。局空间内的命名冲突,即重名问题。大型应用系统常常由许多人来设计完成,命名大型应用系统常常由许多人来设计完成,命名冲突是一种潜在的
2、危险,程序员必须细心地定义标冲突是一种潜在的危险,程序员必须细心地定义标识符,以保证名字的惟一性。识符,以保证名字的惟一性。一个标识符可在多个命名空间中定义,它在不同命一个标识符可在多个命名空间中定义,它在不同命名空间中的含义是互不相干的。这样,在一个新的命名名空间中的含义是互不相干的。这样,在一个新的命名空间中可定义任何标识符,它们不会与任何已有的标识空间中可定义任何标识符,它们不会与任何已有的标识符发生冲突,因为已有的定义都处于其它命名空间中。符发生冲突,因为已有的定义都处于其它命名空间中。例如,设例如,设Bill是是X公司的员工,工号为公司的员工,工号为123,而,而John是是Y公司的
3、员工,工号也是公司的员工,工号也是123。由于两人在不同。由于两人在不同的公司工作,可以使用相同的工号来标识而不会造成混的公司工作,可以使用相同的工号来标识而不会造成混乱,这里每个公司就表示一个独立的命名空间。如果两乱,这里每个公司就表示一个独立的命名空间。如果两人在同一家公司工作,其工号就不能相同了,否则会发人在同一家公司工作,其工号就不能相同了,否则会发生混乱。生混乱。2.4.1 2.4.1 为什么要引入为什么要引入命名空间命名空间 这一特点是使用命名空间的主要理由。在大型的计算这一特点是使用命名空间的主要理由。在大型的计算机程序中,往往会出现成百上千个标识符。命名空间提供机程序中,往往会
4、出现成百上千个标识符。命名空间提供了一种了一种隐藏区域标识符隐藏区域标识符的机制。通过将逻辑上相关的标的机制。通过将逻辑上相关的标识符组织成相应的命名空间,可使整个系统更加模块化。识符组织成相应的命名空间,可使整个系统更加模块化。在编程语言中,命名空间是一种特殊的作用域,它包在编程语言中,命名空间是一种特殊的作用域,它包含了处于该作用域内的标识符,且本身也用一个标识符来含了处于该作用域内的标识符,且本身也用一个标识符来表示,这样便将一系列在逻辑上相关的标识符用一个标识表示,这样便将一系列在逻辑上相关的标识符用一个标识符组织了起来。许多现代编程语言都支持命名空间。符组织了起来。许多现代编程语言都
5、支持命名空间。2.4.1 2.4.1 为什么要引入为什么要引入命名空间命名空间 花花括括号号括括起起来来的的部部分分称称声声明明块块。声声明明块块中中可可以以包包括括:类类、变变量量(带带有有初初始始化化)、函函数数(带带有有定定义义)等等。在在域域外外使使用用域域内内的的成成员员时时,需需加加上上名名字字空空间间名名作作为为前前缀缀,后后面面加加上上域域操操作作符符“:”。这这里里添添加加了了名名字字空空间间名名称称的的成成员员名名被被称称为为限限定定修修饰饰名名。如如:ns1:ans1:a,ns1:fun1ns1:fun1()()等等。等等。最最外外层层的的名名字字空空间间域域称称为为全全
6、局局名名字字空空间间域域(global global namespace scopenamespace scope),即文件域。),即文件域。namespace ns1 float a,b,c;fun1()声明块声明块声明块声明块2.4.2 2.4.2 如何创建命名空间如何创建命名空间命名空间名命名空间名命名空间名命名空间名2.4.2 2.4.2 如何创建命名空间如何创建命名空间 名字空间域可分层嵌套,有分层屏蔽作用。例如:名字空间域可分层嵌套,有分层屏蔽作用。例如:namespacenamespace n1 n1 namespacenamespace n2 n2/名字空间嵌套名字空间嵌套 c
7、lassclass matrix matrix 访问访问matrixmatrix,可写:,可写:n1:n2:matrix n1:n2:matrix。namespace ns1 float a,b,c;fun1()声明块声明块声明块声明块命名空间名命名空间名命名空间名命名空间名2.4.3 2.4.3 如何访问命名空间成员如何访问命名空间成员1.使用使用域操作符域操作符直接访问直接访问2.使用使用using 声明声明3.使用使用using 指令指令访问命名空间成员,有三种方法:访问命名空间成员,有三种方法:ns1:a n1:n2:matrix#includeusing namespace std;
8、namespace A int x=1;namespace B int x=2;void main()int y=x;int a=A:x;int b=B:x;coutabendl;/error C2065:x:undeclared identifier/OK例例使用使用using声明可只写一次声明可只写一次 限定修饰名限定修饰名using声明以关键字声明以关键字using开头,后面是被限开头,后面是被限定修饰的名字空间成员名,例如:定修饰的名字空间成员名,例如:using n1:n2:matrix;以后在程序中使用以后在程序中使用matrix时,就可以直接使时,就可以直接使用成员名,而不必使用
9、限定修饰名。用成员名,而不必使用限定修饰名。2.使用使用using 声明声明#includeusing namespace std;namespace A int x=1;namespace B int x=2;void main()int y=x;int a=A:x;int b=B:x;coutabendl;using A:x;int a=x;例例 使用使用using指示符,可以一次性地使名字指示符,可以一次性地使名字空间中所有成员都可以直接被使用,比空间中所有成员都可以直接被使用,比using声明更方便。声明更方便。using指示符以关键字指示符以关键字using开头,后面开头,后面是关键
10、字是关键字namespace,然后是名字空间名。,然后是名字空间名。3.使用使用using指示符指示符using namespace std;3.使用使用using指示符指示符 标准标准C+C+库中的所有组件都是在一个被称为库中的所有组件都是在一个被称为stdstd的名的名字空间中声明和定义的。因此,在采用标准字空间中声明和定义的。因此,在采用标准C+C+的平台的平台上使用标准上使用标准C+C+库中的组件,只要写上这个库中的组件,只要写上这个usingusing指示指示符,就可以直接使用符,就可以直接使用标准标准标准标准C+C+C+C+库库库库中的所有成员。中的所有成员。注意:注意:如果使用了
11、名空间如果使用了名空间stdstd,则在使用,则在使用#include#include编编译预处理命令包含头文件时,必须去掉头文件的扩展译预处理命令包含头文件时,必须去掉头文件的扩展名名.h.h,否则会出错。,否则会出错。#includeusing namespace std;namespace A int x=1;namespace B int x=2;void main()int y=x;int a=A:x;int b=B:x;coutabendl;例例using namespace A;int a=x+y;int y;通常定义变量(或对象),编译器在编译时都可以根据该通常定义变量(或对象
12、),编译器在编译时都可以根据该通常定义变量(或对象),编译器在编译时都可以根据该通常定义变量(或对象),编译器在编译时都可以根据该变量(或对象)的类型知道所需内存空间的大小,从而系统在变量(或对象)的类型知道所需内存空间的大小,从而系统在变量(或对象)的类型知道所需内存空间的大小,从而系统在变量(或对象)的类型知道所需内存空间的大小,从而系统在适当的时候为他们分配确定的存储空间。这种内存分配称为适当的时候为他们分配确定的存储空间。这种内存分配称为适当的时候为他们分配确定的存储空间。这种内存分配称为适当的时候为他们分配确定的存储空间。这种内存分配称为静静静静态存储分配态存储分配态存储分配态存储分
13、配。有些对象只有在程序运行时才能确定,这样编译器在编译有些对象只有在程序运行时才能确定,这样编译器在编译有些对象只有在程序运行时才能确定,这样编译器在编译有些对象只有在程序运行时才能确定,这样编译器在编译时就无法为他们预定存储空间,只能在程序运行时,系统根据时就无法为他们预定存储空间,只能在程序运行时,系统根据时就无法为他们预定存储空间,只能在程序运行时,系统根据时就无法为他们预定存储空间,只能在程序运行时,系统根据运行时的要求进行内存分配,这种方法称为运行时的要求进行内存分配,这种方法称为运行时的要求进行内存分配,这种方法称为运行时的要求进行内存分配,这种方法称为动态存储分配动态存储分配动态
14、存储分配动态存储分配。当当当当程程程程序序序序运运运运行行行行到到到到需需需需要要要要一一一一个个个个动动动动态态态态分分分分配配配配的的的的变变变变量量量量或或或或对对对对象象象象时时时时,必必必必须须须须向向向向系系系系统统统统申申申申请请请请取取取取得得得得堆堆中中中中的的的的一一一一块块块块所所所所需需需需大大大大小小小小的的的的存存存存贮贮贮贮空空空空间间间间,用用用用于于于于存存存存贮贮贮贮该该该该变变变变量量量量或或或或对对对对象象象象。当当当当不不不不再再再再使使使使用用用用该该该该变变变变量量量量或或或或对对对对象象象象时时时时,要要要要显显显显式式式式释释释释放放放放它它它
15、它所所所所占占占占用用用用的的的的存存存存贮贮贮贮空空空空间间间间,这这这这样样样样系系系系统统统统就就就就能能能能对对对对该该该该堆堆堆堆空空空空间间间间进进进进行行行行再再再再次次次次分分分分配配配配,做做做做到到到到重复使用有限的资源。重复使用有限的资源。重复使用有限的资源。重复使用有限的资源。2.8 2.8 动态内存的分配与释放动态内存的分配与释放 在程序运行时可使用的内存空间称为在程序运行时可使用的内存空间称为堆堆(heap)heap),堆内存就是在程序运行时获得堆内存就是在程序运行时获得的内存空间,在程序编译和连接时不必确定的内存空间,在程序编译和连接时不必确定它的大小,它随着程序
16、的运行过程变化,时它的大小,它随着程序的运行过程变化,时大时小,因此堆内存是动态的,堆内存也称大时小,因此堆内存是动态的,堆内存也称为动态内存。为动态内存。new运算符用于申请所需的内存空间,返回指定类型的一个指针(常量,即内存空间首地址)。它的语法格式为:指针变量指针变量 =new 数据类型;其中,指针变量应预先声明,指针变量指向的数据类型与new后面的数据类型相同。若申请成功,则返回分配空间的首地址赋给指针变量;否则(如没有足够的内存空间)返回0(NULL一个空指针)。例如:例如:int *p;p=new int;(20);系统为指针p p开辟了一个用来保存int类型数据的内存空间(在申请
17、时,也可以进行初始化)。new 运算符在在在在C+C+C+C+中,申请和释放堆中分配的存贮空间,分别使用中,申请和释放堆中分配的存贮空间,分别使用中,申请和释放堆中分配的存贮空间,分别使用中,申请和释放堆中分配的存贮空间,分别使用newnewnewnew和和和和deletedeletedeletedelete两个运算符来完成,其使用的格式如下:两个运算符来完成,其使用的格式如下:两个运算符来完成,其使用的格式如下:两个运算符来完成,其使用的格式如下:例如:例如:int *p;p=new int20;系统为指针p p开辟了一个用来保存int类型数组的内存空间,数组中有20个元素。也可以用new运
18、算符申请一块保存数组的内存空间,即动态创建一个数组动态创建一个数组动态创建一个数组动态创建一个数组。格式为:指针变量new 数据类型数组大小;其中,数组大小给出数数组组元元素素的的个个数数,指针指向分配的内存空间首首地地址址,指针的类型与new后的数据类型相同。new 运算符 当程序中不再使用由运算符new申请的某个内存空间时,可以用delete运算符释放它。它的语法格式为:delete 指针变量;delete 常量指针变量;它的功能是释放由new申请到的内存空间。其中指针变量是指向需要释放内存空间的指针变量名字,并且delete只是删除动态内存空间,并不是将指针变量本身删除。常量可以省略,且
19、不用考虑数组的维数。int *p1=new int;int *p2=new int 20;delete p1;delete p2;delete 运算符v 1.1.newnewnewnew 运算符返回的是一个指向所分配类型变量(对象)运算符返回的是一个指向所分配类型变量(对象)的的指针指针。对所创建的变量或对象,都是通过该指针来间接操作。对所创建的变量或对象,都是通过该指针来间接操作的,而的,而动态创建的对象本身没有名字动态创建的对象本身没有名字动态创建的对象本身没有名字动态创建的对象本身没有名字。v 2.2.一般定义变量和对象时要用标识符命名,称一般定义变量和对象时要用标识符命名,称命名对象命
20、名对象命名对象命名对象,而,而动态所创建的变量或对象称动态所创建的变量或对象称无名对象无名对象无名对象无名对象。堆区是不会自动在分配。堆区是不会自动在分配时做初始化的(包括清零),所以必须用初始化式(时做初始化的(包括清零),所以必须用初始化式()来显式来显式初始化。但初始化。但不可对动态数组初始化不可对动态数组初始化不可对动态数组初始化不可对动态数组初始化v 3.3.指针变量指针变量newnew 数据类型数据类型 数组大小数组大小;请注意请注意“数组大小数组大小”不是常量表达式,即它的值不必在编不是常量表达式,即它的值不必在编译时确定,可以在运行时确定。变量译时确定,可以在运行时确定。变量
21、n n 在编译时没有确定的在编译时没有确定的值,而是在运行中输入,值,而是在运行中输入,按运行时所需分配堆空间按运行时所需分配堆空间按运行时所需分配堆空间按运行时所需分配堆空间,这一点,这一点是动态分配的优点,可克服数组是动态分配的优点,可克服数组“大开小用大开小用”的弊端,在表、的弊端,在表、排序与查找中的算法,若用动态数组,通用性更好。排序与查找中的算法,若用动态数组,通用性更好。说明:说明:v 4.4.动态分配失败动态分配失败动态分配失败动态分配失败。返回一个空指针(。返回一个空指针(NULLNULL),表示发生),表示发生了异常,堆资源不足,分配失败。因此,一定要检查分配的内了异常,堆
22、资源不足,分配失败。因此,一定要检查分配的内存指针是否为空,如果是空指针,则不能引用这个指针,否则存指针是否为空,如果是空指针,则不能引用这个指针,否则将造成系统崩溃。将造成系统崩溃。说明:说明:int *p=new int 20;if(p!=NULL)else v 5.5.指针删除与堆空间释放指针删除与堆空间释放指针删除与堆空间释放指针删除与堆空间释放。删除一个指针。删除一个指针p;p;实际意实际意思是删除了思是删除了p p所指的目标(变量或对象等),释放了它所占的所指的目标(变量或对象等),释放了它所占的堆空间,而不是删除本身,释放堆空间后,成了堆空间,而不是删除本身,释放堆空间后,成了空
23、悬指空悬指空悬指空悬指针针针针。v 6.6.动态分配的变量或对象的生命期动态分配的变量或对象的生命期动态分配的变量或对象的生命期动态分配的变量或对象的生命期。无名对象的生无名对象的生无名对象的生无名对象的生命期并不依赖于建立它的作用域,比如在函数中建立的动态对命期并不依赖于建立它的作用域,比如在函数中建立的动态对命期并不依赖于建立它的作用域,比如在函数中建立的动态对命期并不依赖于建立它的作用域,比如在函数中建立的动态对象在函数返回后仍可使用象在函数返回后仍可使用象在函数返回后仍可使用象在函数返回后仍可使用。我们也称堆空间为自由空间(我们也称堆空间为自由空间(free free storesto
24、re)就是这个原因。)就是这个原因。但必须记住释放该对象所占堆空间,但必须记住释放该对象所占堆空间,并只能释放一次,在函数内建立,而在函数外释放是一件很容并只能释放一次,在函数内建立,而在函数外释放是一件很容易易失控失控失控失控的事,往往会出错。的事,往往会出错。说明:说明:v 7 7内存泄漏(内存泄漏(内存泄漏(内存泄漏(memory leakmemory leakmemory leakmemory leak)和重复释放)和重复释放)和重复释放)和重复释放。newnew与与delete delete 是配对使用的,是配对使用的,deletedelete只能释放堆空间。如果只能释放堆空间。如果
25、newnew返返回的指针值丢失,则所分配的堆空间无法回收,称回的指针值丢失,则所分配的堆空间无法回收,称内存泄漏内存泄漏内存泄漏内存泄漏,同一空间重复释放也是危险的,因为该空间可能已另分配,所同一空间重复释放也是危险的,因为该空间可能已另分配,所以必须妥善保存以必须妥善保存newnew返回的指针,以保证不发生内存泄漏,也返回的指针,以保证不发生内存泄漏,也必须保证不会重复释放堆内存空间。必须保证不会重复释放堆内存空间。#include using namespace std;void main()int n;/定义数组元素的个数定义数组元素的个数定义数组元素的个数定义数组元素的个数 int*p
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 面向对象程序设计 面向对象程序设计课件第2章 C+对C的扩充 面向 对象 程序设计 课件 C+ 扩充