C++C++C++C++名字空间说明字号:[大中小]发布日期:2009-11-30发布者:admin浏览次数:130次C++C++C++C++名字空间说明1111名字空间介绍在面对数百种第三方库,这还未提及C++可以接受的程序设计库,程序员有时会发现提供确信不和其他符号冲突的变量名和函数名是一个挑战,标准C++解决这类日益增多的问题的办法就是使用名字空间,它是标识符使用范围的一个附加层,能够使一个程序员创造有意义的符号名称而不必顾及所有其他人的工作。简而言之,名字空间既为一个名字范围区域,名字空间中所有由程序员创建的标识符可以确保是唯一的——假设程序员在名字空间中没有声明两个重名的标识符;并假设以前以定义的同名名字空间已不存在。可以像这个定义一个简单的名字空间:namespaceMyNames{intiVal1=100;intiVal2=200;}这里有两个整型变量iVal1和iVal2被定义为MyNames名字空间的组成部分。当然,这仅仅是一个介绍性的例子。在本章的后续部分,可以更详细的考察名字空间的定义。2222名字空间的成员名字空间的一个例子就是std,它是C++定义其库标识符的名字空间。为使用cout流对象,你必需告诉编译器cout已存在于std名字空间中。为达到上述目的可以指定名字空间的名称和作用域限定操作符(::)作为cout标识符的前缀。如清单1-1程序所示:///////////////////////////////////清单1-1//文件名:Test.cpp////////////////////////////////#includeiostreamintmain(){std::couthello;return0;}清单1-1通过使用cout对象将流文本输出到屏幕上来显示短信息。注意std名字空间是如何出现在cout对象名称前面的,这是到目前为止我们应该乐于接受的惯例。3333usingusingusingusingnamespacenamespacenamespacenamespace语句使用已在名字空间定义的标识符的另一种方法是将usingnamespace语句包含在涉及到名字空间的源代码文件中。例如:清单1-2是清单1-1的别一种形式,它包含了usingnamespace语句。///////////////////////////////////清单1-2//文件名:Test1.cpp////////////////////////////////#includeiostreamusingnamespacestd;intmain(){couthello;return0;}清单1-2的结果同清单1-1完全一样。然而,应该感谢usingnamespace语句,程序员不再需要在cout流对象名称前加上std名字空间名称。不仅cout标识符不再需要std前缀,而且在std名字空间定义的其他任何标识符都是如此,因此这种方式可能节约大量的时间。然而请注意,并没有一种可以推荐的程序设计惯例,因为使用名字空间语句基本上是在全局层次设置特定的名字空间。这几乎违背了名字空间最初的目标。清单1-3示例了在将usingnamespace语句包含于程序中可能遇到的问题。///////////////////////////////////清单1-3//文件名:Test2.cpp////////////////////////////////#includeiostreamnamespaceMyNames{intiVal1=100;intiVal2=200;}namespaceMyOtherNames{intiVal1=300;intiVal2=400;}usingnamespacestd;usingnamespaceNyNames;usingnamespaceNyOtherNames;intmain(){couthello;iVal1=100;return0;}当试图编译清单1-3中的程序时,大多数均会提示相应的出错信息。在为在语句iVal1=100中,编译器并不知道程序所指的是iVal1的哪种版本。是在MyNames中定义的iVal1还是在MyOtherNames定义的iVal1呢?编译器并没有办法识别。为了避免出现这种类型的问题,应该将如清单1-3中所示的程序改写,如清单1-4所示,程序将会被正确的编译和执行。///////////////////////////////////清单1-4//文件名:Test3.cpp////////////////////////////////#includeiostreamnamespaceMyNames{intiVal1=100;intiVal2=200;}namespaceMyOtherNames{intiVal1=300;intiVal2=400;}intmain(){std::couthello;MyNames::iVal1=100;return0;}4444定义名字空间一个名字空间可以包含多种类型的标识符,如下面所列:�变量名�常量名�函数名�结构名�类名�名字空间名一个名字空间可以在两个地方被定义:在全局范围层次或者是在另一个名字空间中被定义(这样就形成一个嵌套名字空间)。清单1-5给出了一个定义各种类型变量和函数的名字空间定义。///////////////////////////////////清单1-5//文件名:Test4.cpp////////////////////////////////#includeiostreamnamespaceNyNames{constintMAX_LENGTH=100;intiVali=100;longiVal2=200L;charcr='Z';intAdd(inti,intj){returni+j;}longSub(longi,longj){returni-j;}}intmain(){std::coutNyNames::Add(NyNames::MAX_LENGTH,NyNames::iVali);std::coutNyNames::Sub(NyNames::iVal2,NyNames::cr);return0;}5555嵌套名字空间名字空间可以在其他名字空间中被定义。在这种情况下,仅仅通过使用外部的名字空间作为前缀,一个程序就可以引用名字空间之外定义的其他标识符。然而在名字空间内部定义的标识符需要作为外部和内部名字空间名称的前缀出现。清单1-6示例了嵌套名字空间。///////////////////////////////////清单1-6//文件名:Test5.cpp////////////////////////////////#includeiostreamnamespaceMyOutNames{intiVal1=100;intiVal2=200;namespaceMyInnerNames{intiVal3=300;intiVal4=400;}}intmain(){std::coutMyOutNames::iVal1std::endl;std::coutMyOutNames::iVal2std::endl;std::coutMyOutNames::MyInnerNames::iVal3std::endl;std::coutMyOutNames::MyInnerNames::iVal4std::endl;return0;}6666无名名字空间尽管给定名字空间的名称是有益的,但你可以通过在定义中省略名字空间的名称而简单地声明无名名字空间,例如:下面的例子定义了一个无名名字空间,它包含了两个整型变量。namespaceMyNames{intiVal1=100;intiVal2=200;}事实上,在无名名字空间中定义的标识符被设置为全局的名字空间,这几乎彻底破坏了名字空间设置的最初目标。基于这个原因,无名名字空间并未被广泛应用。7777名字空间的别名可以给定名字空间的别名,它是已定义的名字空间的可替换的名称。通过将别名指定给当前的名字空间的名称,你可以简单地创建一个一个名字空间的别名。清单1-7说明了名字空间别名的使用。///////////////////////////////////清单1-7//文件名:Test6.cpp////////////////////////////////#includeiostreamnamespaceMyNames{intiVal1=100;intiVal2=200;}namespaceMyAlias=MyNames;intmain(){std::coutMyAlias::iVal1std::endl;std::coutMyAlias::iVal2std::endl;return0;}8888名字空间综合举例通过上面的学习我们了解了什么是名字空间以及名字空间的用途,也举了大量的例子说明了名字空间的使用;但以上我们都是以单文件的形式说明名字空间的,然而我们知道C++程序是由头文件和源文件组成的;例如我产在头文件中定义了一个名字空间,且在名字空间中定义了一个类,那么如果在源文件中实现这个类呢?清单1-8说明了这种其实现方法。///////////////////////////////////清单1-8//文件名:Test7.h////////////////////////////////#ifndefTEST_H#defineTEST_HnamespaceMyNames{classTestClass{public:,;,;voidPrintVal();TestClass(intiVal);private:intm_iVal;};}#endif///////////////////////////////////清单1-8//文件名:Test7.cpp////////////////////////////////#includeiostream#includeTest7.hnamespaceMyNames{TestClass::TestClass(intiVal){m_iVal=iVal;}voidTestClass::PrintVal(){std::coutm_iValstd::endl;}}///////////////////////////////////清单1-8//文件名:call.cpp////////////////////////////////#includeiostream#includeTest7.hintmain(){MyNames::TestClassrTest(800);rTest.PrintVal();return0;}