当我们在采用不同的模块或程序库时,经常会出现名称冲突的现象,这是因为不同的模块和程序库可能对不同的对象使用相同的标识符(identifier)。Namespace 正是用来解决这种名称冲突问题的。
所谓的 namespace 指标识符的某种可见范围。和 class 不同,namespace 具有扩展开放性,可发生于任何源码文件上。因此,你可以使用一个 namespace 来定义若干组件,而它们可散布于多个实质模块内。这类组建的典型例子就是 C++标准库,在C++标准库内就使用了一个namespace。
对于C++标准库中的所有标识符都被定义于一个名为 std 的 namespace 内。C++11还包含由 TR1引入,被定义于 namespace std::tr1内的所有标识符。此外,namespace posix 被保留,虽然尚未被C++11标准库使用。
对于以下namespace 嵌套于 std 内,被C++标准库使用:
std::rel_ops;
std::chrono;
std::placeholders;
std::regex_constants;
std::this_thread;
基于 namespace 带来的概念,如果要使用C++标准库任何标识符,你拥有三种选择:
1:直接指定标识符,例如写下 std::ostream 而不是 ostream。
std::cout<<3.4<<std::endl;
2:使用 using declaration。例如以下程序片段使我们后续不必写出范围限定符 std:: 便可以直接使用 cout 和 endl :
using std::cout;
using std::endl;
于是,先前的例子可写为:
cout<<3.4<<endl;
3:使用 using directive,这是最简便的选择,例如对namespace std 采用 using directive ,便可以让std内的所有标示符都有效,就好像它们被声明为全局符号一样。因此当写下:
using namespace std;
之后,就可以直接使用std 所表示的所有标识符,例如:
#include<iostream>
#include<string>
using namespace std;
int main()
{
string a{"234"};
cout<<a<<endl;
return 0;
}
但是在复杂的代码中,第三种方式可能导致以外的名称冲突,对于更糟的情况,由于某些晦涩的重载规则甚至导致不一样的行为。如果对于使用场景不明确(例如在头文件中),因避免使用第三种方式。