Chinaunix首页 | 论坛 | 博客
  • 博客访问: 291007
  • 博文数量: 148
  • 博客积分: 4365
  • 博客等级: 上校
  • 技术积分: 1566
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-05 21:38
文章分类
文章存档

2014年(2)

2013年(45)

2012年(18)

2011年(1)

2009年(54)

2008年(28)

我的朋友

分类: C/C++

2008-11-04 11:57:02

    变量的名字在其所处的域内必须唯一,这点毫无疑问。但是对于大型程序来讲,代码繁多,在全局域内是有可能发生名字碰撞的,虽然靠定义足够长的名字可以解决此问题,但是会使程序员的负担加重。C++中的名字空间应运而生。名字空间可以将全局域划分,这样来自不同库中的代码中即使有名字相同的变量也不会发生碰撞,前提是他们拥有自己的名字空间。

namespace section17{
int i;
}

这样我们定义了一个名为section17的名字空间,在其内部可以定义任何需要的东西,也包括嵌套的名字空间,不同于类或结构体定义,名字空间定义的结尾没有分号

名字空间的名字在其所处的域内必须是唯一的,它只能在全局域或其它名字空间内定义,不能在函数或类内

名字空间内所定义的成员之间可以直接的互相访问,在空间之外访问需要使用域作用符

section17::i

但是这样使用也很不方便,我们可以使用using语句在代码的开始进行声明

using section17::i;

然后就可以直接使用i了。

名字空间所包含的部分具有累积性(cumulative),一个名字空间可以分成几部分在不同地方分别定义,甚至是在不同的文件中。当然文件A中名字空间S中的成员只在文件A中可见,文件B要是想使用A中的内容,须在本文件的名字空间中加入对使用内容的声明。

名字空间中类定义和相关函数的定义应当放在头文件中,使用这些成员的文件导入这些头文件。
想关类与函数的实现可以放在不同源文件之中。

在任何类,函数,名字空间之外的域属于全局域,也就是全局名字空间(global namespace)

::member_name

上面的用法是使用全局名字空间中的成员

名字空间内部还可以嵌套名字空间,如果有相同的成员名,在嵌套的名字空间内将隐藏(hide)外部的
使用时需要完整的名字

namespace_A::namespace::B::member_name


如果在定义名字空间时如下

namespace{
}

没有为名字空间命名,则该空间就是无名的(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 namespace std;

在含有using指示的域内就可以使用其名字空间内成员的简写了,如直接使用cout。
using知识可以出现在名字空间内,函数内,局部域内,但不可出现在类内。

class ss{
public:
    using namespace std;
};

编译器提示 parse error before `namespace'
using指示将目标空间内的所有名字注入到当前域,对于using指示的使用要慎重,过度的使用也会发生名字碰撞。不推荐这么用,可能造成名字污染(pollution)。

当名字空间A中的函数或重载的运算符有一个A中的类类型的参数(对象,引用,指针均可)时,调用这个函数或重载运算符可直接调用

std::string s;
cin>>s;

而不用写成

using std::cin;
using std::operator>>;
std::operator>>(std::cin,s);

因为编译器会优先到参数所在的名字空间内查找。
名字空间内类的友元函数调用也是如此。

函数重载与名字空间
某名字空间内有些重载函数,在空间外我们想要使用它们,可以用using声明或using指示,using指示不用说了,关于using声明

using namespace_name::function_name;

不要带参数列表,这样所有的重载函数都已引入,类似派生类使用基类的重载函数。
如果两个不同名字空间内的函数名字相同,我们用using声明将它们分别引入后,它们在被引入的域成为重载函数。
阅读(798) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~