名字空间机制是为了解决名字冲突而建立的。比如在程序中定义了一个名为 toupper() 的函数,那么这个函数会覆盖标准库函数中的 toupper() (假设两个函数的参数都相同),这是因为它们的名字都在全局名字空间中。
如果同一个程序中使用了两个或多个第三方库,名字冲突将变得更为复杂。此时,很可能发生在一个库中定义的名字和另一个库中具有同样的名字而冲突的情况。
namespace 关键字的目的就是为了解决上述的名字冲突问题。在名字空间中声明的名字只在局部作用域内可见,所以通过名字空间,我们可以在不同的程序上下文中使用同样的名字而不引起冲突。在 namespace 出现之前,整个 C++ 库都定义在全局名字空间之中(唯一的名字空间),而在其后,C++ 库则是定义在 std 这个名字空间中,这样在很大程度上减少了名字冲突的可能性。我们也可以在程序中年自定义自己的名字空间,将我们认为可能会造成冲突的名字定义在该名字空间中,这样,这些名字只会在局部的作用域中可见,从而避免了名字冲突。
使用 namespace 关键字创建声明区域,并以此来划分全局名字空间。从本质上来说,一个 namespace 定义了一个作用域,其通用形式如下:所有在 namespace 中定义的元素都将被限定在这个名字空间的作用域内。
测试代码:
[C++] 纯文本查看 复制代码 // namespace.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
using namespace std;
//声明自己的名字空间
namespace CounterNameSpace {
int upperbound;
int lowerbound;
class counter {
int count;
public:
counter(int n)
{
if (n <= upperbound)
count = n;
else
count = upperbound;
}
void reset(int n)
{
if (n <= upperbound)
count = n;
}
int run() //在名字空间中,函数可以直接使用空间中定义的变量lowerbound
{
if (count > lowerbound)
return count--;
else
return lowerbound;
}
};
}
int _tmain(int argc, _TCHAR* argv[])
{
CounterNameSpace::upperbound = 100; //名字空间外的代码访问名字空间内的成员时需要在成员名前加上作用域解析运算符(::)
CounterNameSpace::lowerbound = 0;
CounterNameSpace::counter ob1(10);
int i;
do {
i = ob1.run(); //声明了counter类型对象后,就无需再次限定对象成员的作用域(这里直接调用 ob1.run()),因为编译器已经知道了对象所在的作用域
cout << i << " ";
}while ( i > CounterNameSpace::lowerbound);
cout << endl;
CounterNameSpace::counter ob2(20);
do {
i = ob2.run();
cout << i << " ";
} while ( i > CounterNameSpace::lowerbound);
cout << endl;
ob2.reset(100);
CounterNameSpace::lowerbound = 90;
do {
i = ob2.run();
cout << i << " ";
}while (i > CounterNameSpace::lowerbound);
return 0;
}
运行输出:10 9 8 7 6 5 4 3 2 1 0
20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
100 99 98 97 96 95 94 93 92 91 90
此外,同一个名字可以用来声明若干个名字空间。这样一个名字空间就被分散到几个文件,甚至是在同一个文件中,比如:namespace NS {
int i;
}
//...
namespace NS {
int j;
} 上面,名字空间 NS 被划分为两部分。但是每个部分中的内容仍然是在同一个名字空间中的(这里是 NS)。
需要注意的是,必须在其他类型作用域之外声明名字空间,而且也不能在函数中声明一个名字空间。但是一个名字空间可以嵌入到另一个空间之中。 |