基本使用
- namespace ns_name { declarations } 命名空间定义
- inline namespace ns_name { declarations } (since C++11) 类似于 class private 成员,只有在定义的 namespace 中才可见
- namespace { declarations } 匿名命名空间类似声明 static 函数,只在本编译单元(文件)内可见
- ns_name::name 命名空间内成员的使用
- using namspace ns_name; using-directive 将 ns_name 中的名字提升到使用这个语句的 scope
- using ns_name::name; using-declaration 将 ns_name 中的 name 提升到这个语句的 scope
- namespace name = qualified-namespace; 命名空间的别名,嵌套很深的命名空间可以这样方便使用
- namespace ns:name::inline(since C++20)(optional) name {declarations } (since C++17)
嵌套定义
namespace A::B::C {...}
等于namespace A{ namespace B { namespace C {...} } }
namespace A::B::inline C {...}
等于namespace A::B{inline namespace C {...} }
inline
要在除了第一个 namespace 的前面
注意
-
命名空间必须在全局命名空间或者其他命名内定义,比如不能在函数内定义
-
命名空间的扩展 extension-namespace-definition
namespace A { int a = 0; } namespace A { int b = 0; }
-
命名空间成员的定义会影响 name-lookup
Using-declarations
Introduce a name that is defined elsewhere into the declarative region where this using-declaration appears
-
using name 将 name 引入到特定命名空间,有点类似 Rust 模块系统的模块提升
void f(); namespace A { void g(); } namespace X { using ::f; // global f is now visible as ::X::f using A::g; // A::g is now visible as ::X::g using A::g, A::g; // (C++17) OK: double declaration allowed at namespace scope } void h() { X::f(); // calls ::f X::g(); // calls A::g }
-
using 之后 reopen 命名空间的内容不生效
namespace A { void f(int); } using A::f; // ::f is now a synonym for A::f(int) namespace A { // namespace extension void f(char); // does not change what ::f means } void foo() { f('a'); // calls f(int), even though f(char) exists. } void bar() { using A::f; // this f is a synonym for both A::f(int) and A::f(char) f('a'); // calls f(char) }
-
不能引入命名空间,只能引入命名空间内的一个名字,并且在同一个 scope 内的所有限制都一样
namespace A { int x; } namespace B { int i; struct g { }; struct x { }; void f(int); void f(double); void g(char); // OK: function name g hides struct g } void func() { int i; using B::i; // error: i declared twice void f(char); using B::f; // OK: f(char), f(int), f(double) are overloads f(3.5); // calls B::f(double) using B::g; g('a'); // calls B::g(char) struct g g1; // declares g1 to have type struct B::g using B::x; using A::x; // OK: hides struct B::x x = 99; // assigns to A::x struct x x1; // declares x1 to have type struct B::x } //-------- 分隔 namespace B { void f(int); void f(double); } namespace C { void f(int); void f(double); void f(char); } void h() { using B::f; // introduces B::f(int), B::f(double) using C::f; // introduces C::f(int), C::f(double), and C::f(char) f('h'); // calls C::f(char) f(1); // error: B::f(int) or C::f(int)? void f(int); // error: f(int) conflicts with C::f(int) and B::f(int) }
Using-directives
Using-directives are allowed only in namespace scope and in block scope
Using-directive does not add any names to the declarative region in which it appears (unlike the using-declaration), and thus does not prevent identical names from being declared.
namespace D {
int d1;
void f(char);
}
using namespace D; // introduces D::d1, D::f, D::d2, D::f,
// E::e, and E::f into global namespace!
int d1; // OK: no conflict with D::d1 when declaring
namespace E {
int e;
void f(int);
}
namespace D { // namespace extension
int d2;
using namespace E; // transitive using-directive
void f(int);
}
void f() {
d1++; // error: ambiguous ::d1 or D::d1?
::d1++; // OK
D::d1++; // OK
d2++; // OK, d2 is D::d2
e++; // OK: e is E::e due to transitive using
f(1); // error: ambiguous: D::f(int) or E::f(int)?
f('a'); // OK: the only f(char) is D::f(char)
}
一些例子
namespace Q {
namespace V { // V is a member of Q, and is fully defined within Q
// namespace Q::V { // C++17 alternative to the above two lines
class C { void m(); }; // C is a member of V and is fully defined within V
// C::m is only declared
void f(); // f is a member of V, but is only declared here
}
void V::f() // definition of V's member f outside of V
// f's enclosing namespaces are still the global namespace, Q, and Q::V
{
extern void h(); // This declares ::Q::V::h
}
void V::C::m() // definition of V::C::m outside of the namespace (and the class body)
// enclosing namespaces are the global namespace, Q, and Q::V
{}
}