名字空间定义

上传人:桔**** 文档编号:501947666 上传时间:2023-10-27 格式:DOC 页数:35 大小:132KB
返回 下载 相关 举报
名字空间定义_第1页
第1页 / 共35页
名字空间定义_第2页
第2页 / 共35页
名字空间定义_第3页
第3页 / 共35页
名字空间定义_第4页
第4页 / 共35页
名字空间定义_第5页
第5页 / 共35页
点击查看更多>>
资源描述

《名字空间定义》由会员分享,可在线阅读,更多相关《名字空间定义(35页珍藏版)》请在金锄头文库上搜索。

1、名字空间定义缺省情况下,在全局域(也被称作全局名字空阎域, global namespace scope)中声明的每个对象、函数、类型或模板都引入了一个全局实体( global entity)。在全局名字空间域引入的全局实体必须有惟一的名字。例如,函数和对象不能有相同的名字,无论它们是否在同一程序文本文件中被声明。这意味着,如果我们希望在程序中使用一个库,那么我们必须保证程序中的全局实体的名字不能与库中的全局实体名字冲突。如果程序是由许多厂商提供的库构成的,那么这将很难保证,各种库会将许多名字引入到全局名字空间域中。在组合不同厂商的库时,我们该怎样确保程序中的全局实体的名字不会与这些库中声明的

2、全局实体名冲突?名字冲突问题也被称为全局名字空间污染(global namespace pollution) M题。程序员可以通过使全局实体名字很长,或者在程序中的名字前面加个特殊的字符序列前缀,从而避免这些问题。例如:class cplusplusprimer一mair工x;void工verse(cplusplusprimer一matrlx);但是,这种方案不是很理想。用C十写的程序中可能有相当数目的全局类、函数和模板在整个程序中都是可见的。对程序员来说,用这么长的名字写程序实在是个累赘。名字空间允许我们更好地处理全局名字空间污染问题。库的作者可以定义一个名字空间,从而把库中的名字隐藏在全局

3、名字空间之外。例如:fldtti6SPdC6 CpllSPIUSpylthglc las smat rix“; void Inverse( matrrx); 名字空间cpluspluswrimer是用户声明的名字空间(和全局名字空间不同,后者被隐式声明,并且存在于每个程序之中)每个用户声明的名字空间代表一个不同的名字空间域。用户声明的名字空间域可以包含其他嵌套的名字空间定义,以及函数、对象、模板和类型的声明或定义。在一个名字空间内声明的实体被称为名字空间成员(namespace member)。与全局名字空间域的情形一样,用户声明的名字空间中的每个名字必须指向该名宇空间内的惟一实体。但是,因为

4、不同的用户声明的名字空间引人了不同的域,所以不同的用户声明的名字空间可以具有相同名字的成员。名字空间成员的名字会自动地与该名字空间名复合或被其限定修饰( qualified)。例如,在名字空间 cplusplusprimer中声明的 matrix类的名字是cplusplusprimer:matrix, Inverse函数的名字是CplusplUSWflthCf:IllV6fSC()。在程序中我们可以用限定修饰名来使用名字空间cpluspluswrimer的成员,如下所示:VOid funC(CplllsplllS一pIliner:matriXm)cplusplusprrmer : Invers

5、e(m);return m;如果另一个用户声明的名字空间(如 DiseyFeatureAnimation)也提供了一个matrix类,而且我们希望使用这个类,而不是在名字空间cpluspluswrimer中定义的类、则需要修改func(),如下所示:void func(DisneyFeatureAnimation:matrixm) D;sneyFeatureAnlrnatlon:nnverse(m);return rn; 当然,总是用限定修饰名来引用名字空间成员会比较麻烦namespacename: membername因为这个原因,C十提供了一些机制,比如名字空间别名( namesP。e a

6、liase)、using声明( using declaration)、 using指示符( using directive),使得在程序中使用名字空间成员更容易一些。我们将在86节中展示这些机制。851名字空间定义用户声明的名字空间定义以关键字namespace开头,后面是名字空间的名字。该名字在它被定义的域中必须是谁一的。如果在同样的名字空间域中有其他实体与被定义的名字空间同名,就会发生错误。当然,这意味着名字空间定义并没有消除全局名字空间污染问题。但是,使用名字空间大大地缓解了这个问题。在名字空间名之后是由花括号()括起来的声明块。所有可以出现在全局名字空间域中的声明都可以被放在用户声明的

7、名字空间中:类、变量(带有初始化)、函数(带有定义)以及模板。把一个声明放在用户声明的名字空间中并不会改变其意义。惟一的不同是,这样的声明所引人的名字要与名字空间名复合起来。例如:namespace cplusplusDr工iner class matrix”“; void Inverse( matrix);matrix operator(const matrixml,const matrixmZ) ”COOSt dollblll pi 31416; 在名字空间cplusplusMimer中声明的类的名字是:CpllspluSNf工e工:tatrlx函数的名字是:pinp工u8rel:工ers

8、e()常量的名字是:Cpl:SpluspSllel:pl类、函数、常量的名字被声明它的名字空间的名字限定修饰:这些名字被称为限定修饰名(qualified name)名字空间的定义不一定是连续的。例如,可以如下定义前面的名字空间:naThespace cpluspluspr工iner class matrix“”;COOSt dollblll pi 31416; namespace cplusplus一primer void Inverse( matrix);matrix operator(const matrixml,constfuatrixmZ) “ 前面两个例子是等价的,它们定义的名字空

9、间cPlusPluswrimer都包含类matrix、函数inverse()、常量pi以及operator()。因此,名字空间的定义是可累积的。在下面这一f工:namespace namespacenaae如果namespaceiname没有引用前面已经定义过的名字空间,那么它就会定义一个新的名字空间,否则,它将打开原来的名字空间,以便加入新的声明。名字空间的定义可以非连续,这对生成一个库很有帮助。它使我们更容易将库的源代码组织成接口和实现部分。例如:名字空间的这部分定义了库接口namespace cplusplusprfu erclass matrix”“; COOSt dOSblS pi

10、31416;matrix operator(const matrixml,constmatrixmZ); void Inverse( matrix); 名字空间的这部分定义了库实现namespace cplusplusprimer void Inverse( rnatrrxm) ” matrix operator( constmatrixml, const matrixmZ)” 该名字空间的第一部分给出了描述库接口的声明和定义:类型定义、常量定义、以及函数声明。该名字空间的第二部分给出了库的详细实现一即,函数定义。对于组织一个库的源代码帮助更大的是,同一个名字空间的定义可以跨越几个不同的程序文

11、本文件。不同程序文本文件的名字空间定义也可以积累起来。所以,我们的库可以组织成如下:一primerh一namespace cplusplusNrrmer class matrix”; C00st dOOIO p土一3工416; matrix operator(const matrixml,const matrixmZ);void工verse(matr工x); primerCinclude”primerh” namespace cpluspluspriner void Inverse( matrixm) “” matrix operator( constmatr土xml, constmatrLx

12、mZ)”使用我们的库的程序可能这样: userC 定义库的接口工nclude”pr工Th erh”void furtc(cplusplus、pr工iner:matrixm)cplusplus、pr工iner:Inverse(m); 这种程序组织方式使我们的库具有模块化特性,这种特性是“向用户隐藏实现细节”所必需的,它允许文件PrlC和userc被编译链接到一个程序中,而不会有编译错误和链接错误。852域操作符(:)用户声明的名字空间成员名自动被加上前缀,名字空间名后面加上域操作符(:)。名字空间成员名由该名字空间名进行限定修饰。使用名字空间成员名,比如 matrix,而不用其名字空间名限定修饰

13、是错误的。编译器不知道名字matrix指的是哪个声明: 定义库接日include”prirerh” 错误:不能找到matrix的声明void func(matrixm);名字空间成员的声明被隐藏在其名字空间中。除非我们为编译器指定查找声明的名字空间,否则编译器将在当前的域及嵌套包含当前域的域中查找该名字的声明。例如,如果前面程序改写为 定义库接口include”primerh” class。air。x”用户定义; oh:找到全局matriX类型vood func( matrrxrn);则找到全局域中的类matrix的定义,该程序能正确编译。因为名字空间成员matrix的声明被隐藏在名字空间cp

14、lusplusprimer中,所以名字空间成员的名字与全局域中声明的类名没有冲突。这就是名字空间能够解决全局名字空间污染问题的原因:名字空间成员的名字不会被找到,除非用户使用域操作符并指定名字空间名字作为前缀。还有其他一些机制可使名字空间成员的声明在其外面也成为可见的。这样的机制被称作using声明( u。lug declaration)、和 llsillg指刁F符(llsillg difeCtiVe)。我们将在下一节中介绍它们。注意,域操作符也可以被用来引用全局名字空间的成员。因为全局名字空间没有名字,所以如下符号: : mernbername指向的是全局名字空间的成员。当全局名字空间的成员被嵌套的局部域中声明的名字隐藏时,这对引用该名字非常有用。下面的例子是一个计算斐波那契序列的函数,设计这个例子的用意是为了说明域操作符怎样被用来引用一个被隐藏的全局名字空间成员。变量max有两个定义。全局声明表示该序列的最大值,局部声明表示期望的序列长度(前面曾提到过,函数的参数被放在函数的局部域中。)m。互的这两个声明在该函数中都必须被访问到。但是,不加修饰地使用m。引用的是局部的声明。为访问全局声明,我们必须使用域操作符:max。下面是实现: unC上U土OSt了emCOOStist ITlll 650D0;COOSt土fitl

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 建筑/环境 > 施工组织

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号