变量的名字在其所处的域内必须唯一,这点毫无疑问。但是对于大型程序来讲,代码繁多,在全局域内是有可能发生名字碰撞的,虽然靠定义足够长的名字可以解决此问题,但是会使程序员的负担加重。C++中的
名字空间应运而生。名字空间可以将全局域划分,这样来自不同库中的代码中即使有名字相同的变量也不会发生碰撞,前提是他们拥有自己的名字空间。
namespace section17{
int i;
} |
这样我们定义了一个名为section17的名字空间,在其内部可以定义任何需要的东西,也包括嵌套的名字空间,不同于类或结构体定义,名字空间定义的
结尾没有分号。
名字空间的名字在其所处的域内必须是唯一的,
它只能在全局域或其它名字空间内定义,不能在函数或类内。
名字空间内所定义的成员之间可以直接的互相访问,在空间之外访问需要使用域作用符
但是这样使用也很不方便,我们可以使用using语句在代码的开始进行声明
然后就可以直接使用i了。
名字空间所包含的部分具有累积性(cumulative),一个名字空间可以分成几部分在不同地方分别定义,甚至是在不同的文件中。当然文件A中名字空间S中的成员只在文件A中可见,文件B要是想使用A中的内容,须在本文件的名字空间中加入对使用内容的声明。
名字空间中类定义和相关函数的定义应当放在头文件中,使用这些成员的文件导入这些头文件。想关类与函数的实现可以放在不同源文件之中。
在任何类,函数,名字空间之外的域属于全局域,也就是全局名字空间(global namespace)
上面的用法是使用全局名字空间中的成员
名字空间内部还可以嵌套名字空间,如果有相同的成员名,在嵌套的名字空间内将隐藏(hide)外部的
使用时需要完整的名字
namespace_A::namespace::B::member_name |
如果在定义名字空间时如下
没有为名字空间命名,则该空间就是无名的(unamed)。
无名空间只在声明它的本文件内可见,不可跨文件定义或使用,因为每个文件都刻有自己的无名空间。
无名空间中的名字
必须与全局域中存在的名字
相异,否则会提示变量重复定义。
如果一个头文件里含有无名空间,则在每个导入其的文件内使用的是不同域。
在c中使用static关键字表示该名字的链接属性是是文件内部,
在C++中推荐使用无名空间。使用名字空间内成员的3中方法:
1.using声明(using declaration),形如
using std::cout;
using std::cin; |
一个using生命一次只能声明一个名字,
不要在头文件的局部域(如函数内)以外的地方,如文件开始使用using声明,那样将使命字覆盖整个文件及导入该头文件的文件。
局部域内using声明的名字在该局部域结束时也将失去生命,在该局部域内,如与外部域有名字碰撞,将hide外部域的名字。
2.空间别名(namespace alias)
空间别名是为了简化那些原空间名很长的名字空间准备的
namespace s17=section17; s17::i=0;
|
一个空间可以有多个别名,与原名可以交互地使用。
3.using指示(using directive)
这个最熟悉了
在含有using指示的域内就可以使用其名字空间内成员的简写了,如直接使用cout。
using知识可以出现在名字空间内,函数内,局部域内,但不可出现在类内。
class ss{
public:
using namespace std;
}; |
编译器提示 parse error before `namespace'
using指示将目标空间内的所有名字注入到当前域,对于using指示的使用要慎重,过度的使用也会发生名字碰撞。
不推荐这么用,可能造成名字污染(pollution)。
当名字空间A中的函数或重载的运算符有一个A中的类类型的参数(对象,引用,指针均可)时,调用这个函数或重载运算符可直接调用
而不用写成
using std::cin;
using std::operator>>;
std::operator>>(std::cin,s);
|
因为编译器会优先到参数所在的名字空间内查找。
名字空间内类的友元函数调用也是如此。
函数重载与名字空间
某名字空间内有些重载函数,在空间外我们想要使用它们,可以用using声明或using指示,using指示不用说了,关于using声明
using namespace_name::function_name; |
不要带参数列表,这样所有的重载函数都已引入,类似派生类使用基类的重载函数。
如果两个不同名字空间内的函数名字相同,我们用using声明将它们分别引入后,它们在被引入的域成为重载函数。
阅读(822) | 评论(0) | 转发(0) |