命名空间提供了一种在大项目中避免名字冲突的方法。
在命名空间块内声明的符号被放入一个被命名(具名)的作用域中,避免这些符号被误认为其他作用域中的同名符号。
多个命名空间块的名字可以相同,这些块中的所有声明在该具名作用域声明。
基本语法:inline(可选) namespace 属性(可选) 标识符 { 命名空间体 }
- inline
:存在时,表明此命名空间时内联命名空间。如果原初命名空间定义不使用
inline``,那么不能出现在扩展命名空间定义中。(内联命名空间可以把空间内函数和类型导出到父命名空间中)-
inline
可以出现在除第一个namespace
之外的任意namespace
之前。
-
示例一:
namespace S1 {
void foo() {}
}
namespace S2 {
void foo() {}
}
using namespace S1;
int main()
{
foo();
S2::foo();
}
以上是命名空间的一个典型例子,例子中命名空间S1和S2都有相同的函数foo,在调用两个函数时,由于命名空间S1被using
关键字打开,因此S1的foo函数可以直接使用,而S2的foo函数需要使用::来指定函数的命名空间。
示例二:内联命名空间
#include <iostream>
namespace Parent {
namespace Child1
{
void foo() { std::cout << "Child1::foo()" << std::endl; }
}
inline namespace Child2
{
void foo() { std::cout << "Child2::foo()" << std::endl; }
}
}
int main()
{
Parent::Child1::foo();
Parent::foo();
}
在上面的代码中,Child1不是一个内联命名空间,所以调用Child1的foo函数需要明确指定所属命名空间。而调用Child2的foo函数则方便了许多,直接指定父命名空间即可。
示例三:嵌套命名空间
namespace A::B::C {
int foo() { return 5; }
}
上述代码等价于:
namespace A {
namespace B {
namespace C {
int foo() { return 5; }
}
}
}
示例四:无名命名空间
namespace
{
int i; // 定义 ::(独有)::i
}
void f()
{
i++; // 自增 ::(独有)::i
}
namespace A
{
namespace
{
int i; // A::(独有)::i
int j; // A::(独有)::j
}
void g() { i++; } // A::(独有)::i++
}
using namespace A; // 从 A 引入所有名称到全局命名空间
void h()
{
i++; // 错误:::(独有)::i 与 ::A::(独有)::i 均在作用域中
A::i++; // OK:自增 A::(独有)::i
j++; // OK:自增 A::(独有)::j
}
虽然无名命名空间中的名字可以声明为具有外部连接,但从其他翻译单元无法访问它们,因为它的命名空间名是独有的。
无名命名空间以及所有直接或间接在无名命名空间内声明的命名空间都具有内部连接,这表示在无名命名空间内声明的所有名字都具有内部连接。