一、什么是 namespace
1.1 C语言标识符作用域的缺陷
在C语言中因为项目需要会定义各种全局变量、函数等,我们也会调用C语言标准库提供给我们的各种函数,这将会导致我们变量名、函数名与标准库中的发生命名冲突。
1 2 3 4 5 6 7 8 9
| #include <stdio.h> #include <stdlib.h>
int rand = 10;
int main() { printf("%d\n", rand); }
|

1.2 namespace作用
在C++中通过namespace来防止命名冲突,namespace相当一件隐身衣,在namespace中的变量、函数、类在namespace外面是看不到,访问不到的,相当于不存在,所以也就不会发生命名冲突。即一个命名空间就定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中
二、namespace的定义
定义命名空间使用到namespace关键字,后面跟命名空间的名字,然后接一对{ }即可,{ }中即为命名
空间的成员。空间名字可自定义命名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| namespace kxl { int rand = 10; int sum(int x,int y) { return x+y; } struct Person { char name[10]; int age; }; }
|
2.1 命名空间可以嵌套定义
1 2 3 4 5 6 7 8 9 10
| namespace kxl { int rand = 10; namespace kdl { int x = 0; int rand = 20; } }
|
2.2 可定义重复的命名空间
在一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间,但相同命名空间中的变量、函数、类不能重复定义
1 2 3 4 5 6 7 8 9 10
| namespace kxl { int rand = 10; }
namespace kxl { int x = 20; }
|
最终编译器合并为
1 2 3 4 5 6
| namespace kxl { int rand = 10; int x = 20; }
|
三、namespace使用
3.1 命名空间名称+作用域限定符使用
语法: 空间名称::标识符名
相当于告诉编译器去哪一个命名空间中找哪一个对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| namespace kxl { int rand = 10; int x = 0; int y = 1; namespace kdl { int x = 20; int z = 100; } }
int main() { printf("%d\n", kxl::rand); printf("%d\n", kxl::kdl::x); return 0; }
|
3.2 using将命名空间中成员引入
如果空间中某个对象经常使用,用3.1的方法比较繁琐,可以使用using关键字将空间中某个对象引入,即这个对象不隐身了,作用域为全局作用域
语法: using 空间名称::标识符名;
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| namespace kxl { int rand = 10; int x = 0; int y = 1; }
using kxl::x;
int main() { printf("%d\n",x); return 0; }
|
3.3 使用using namespace将整个空间成员引入
使用using namespace将整个空间成员引入,即隐身衣失效了,空间中所有对象的作用域都是全局作用域,可以直接访问,但是与C++中引入命名空间初衷相矛盾,一般不建议这样用
语法:using namespce 空间名称;
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| namespace kxl { int x = 0; int y = 1; }
using namespace kxl;
int main() { printf("%d\n", x); printf("%d\n", y); return 0; }
|
3.4 命名空间别名
命名空间别名允许为现有的命名空间指定更短或更易记的名称。这样可以简化代码,特别是在使用长命名空间名字时。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #include <iostream>
namespace my_namespace { namespace sub_namespace { void hello() { std::cout << "Hello from SubNamespace!" << std::endl; } } }
namespace alias = my_namespace::sub_namespace;
int main() { alias::hello(); return 0; }
|
四、C++ 11 ~ C++ 20
4.1 C++ 11 内联命名空间
内联命名空间(Inline Namespace)是 C++11 中的一个特性,它允许在命名空间中嵌套另一个命名空间,并且将其内容直接导出到外部命名空间中,即内联命名空间的成员会被视为父命名空间的成员。
语法: inline 空间名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
namespace Test { namespace v1 { void Func() { std::cout << "v1 version" << std::endl; } }
inline namespace v2 { void Func() { std::cout << "v2 version" << std::endl; } } }
Test::v1::Func(); Test::Func();
|
4.2 C++ 17 嵌套命名空间简洁写法
C++17 允许使用简洁写法描述嵌套的命名空间,可以更清晰地表示出命名空间之间的逻辑关系。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| namespace A::B::C { void Fun() { std::cout << "Test()" << std::endl; } }
上面代码等同于: namespace A { namespace B { namespace C { void Fun() { std::cout << "Test()" << std::endl; } } } }
|
4.3 C++ 20
C++ 20支持简洁定义内联命名空间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| namespace A::inline B::C { void Fun() { std::cout << "Test()" << std::endl; } }
上面代码等同于: namespace A { inline namespace B { namespace C { void Fun() { std::cout << "Test()" << std::endl; } } } }
|