C++11标准中,可以在父命名空间中定义内联的子命名空间,内联的子命名空间可以把其包含的名字导入到父命名空间中,从而在父命名空间中可以直接访问子命名空间中定义的名字,而不用通过域限定符Child::name的形式来访问。例如下面的代码:
namespace Parent { namespace Child1 { struct child1_data{int a;} ; } namespace Child2 { struct child2_data{int b;} ; } namespace child3 { child1_data data1; //编译失败 child2_data data2; //编译失败 } }
在命名空间child3中,引用了命名空间Child1和Child2中的名字,由于C++98中不允许跨命名空间的直接使用名字,因而导致编译失败。为了解决这个问题,C++11标准引入了内联的命名空间(inline namespace),下面的代码就可以顺利编译:
namespace Parent { namespace Child1 { struct child1_data{int a;} ; } namespace Child2 { struct child2_data{int b;} ; } namespace child3 { child1_data data1; child2_data data2; } }
注意:匿名的命名空间也可一把其包含的名字导入到父命名空间,但是匿名的命名空间(与使用using打开命名空间一样)无法支持在父命名空间中对匿名的命名口空间中所包含的模板函数进行特化。
缺点:内联的命名空间会破坏命名空间的封装性。
ADL特性(Argument-Dependent name Lookup)
ADL 是C++的一个语言特性,即“参数关联名称查找”,是指当编译器在名字空间找不到一个函数的定义时,就会到这个函数的参数所在的命名空间去查找,比如下面的例子:
#include <iostream> using namespace std; namespace name_ADL { struct St{} ; void ADLfunction(St s){} } int main() { name_ADL::St st ; ADLfunction(st) ; //注意,此处没有用域限定符,但仍然可通过编译 return 0; }
在使用函数ADLfunction时,无需使用其所在的命名空间,因为编译器会去函数参数st所在的命名空间去查找,所以编译器不会报错。由此可见,ADL特性虽然在使用上带来了以下方便,但是却破坏了命名空间原有的封装性。因此,我们在使用名字的时候,最好先用using打开命名空间,或者使用“::”列出函数或变量的完整命名空间。