命名空间
概念
本质:是一个自定义作用域
为什么要用命名空间?
为了解决引入大量库时,导致全局符号的冲突问题。
最基本作用:给不同的库和模块拥有自己独特的作用域
定义与使用
定义一个名字空间,实际上就是定义一个作用域,在名字空间中可以定义变量、函数等。
1
2
3
4
5
6
7
8
9
10
11
12
|
namespace ns
{
//在ns中定义变量
int a=1;
//在ns中定义函数
void printf()
{
std::cout << "命名空间ns中的变量a = " << a << std::endl;
}
}
|
在ns中定义的a,与函数printf的实际名字为 ns::a和ns::printf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
int main()
{
// 方式1:使用 作用域解析符:: 访问命名空间中的成员
std::cout << "直接访问:ns::a = " << ns::a << std::endl;
// 调用命名空间中的函数
ns::print();
// 方式2:使用using声明,简化访问(无需重复写ns::)
using namespace ns;
std::cout << "using后直接访问:a = " << a << std::endl;
print();
return 0;
}
|
操作符::用法
::双冒号操作符,称为作用域引用符,双冒号前面必须是一个作用域
重要的作用:
-
解决命名冲突,明确指定使用哪个空间的变量
-
解决全局变量和局部变量重名的问题,直接写变量名访问局部,加**::**访问全局。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
int a = 666; //全局变量
int main() {
int a = 888; //局部变量
// 不加 :: 优先访问局部变量
std::cout << a << std::endl; // 输出 888
// 加 :: 强制访问全局变量
std::cout << ::a << std::endl; // 输出 666
return 0;
}
|
using语句
可以使用using语句实现导入名字空间
1
2
3
4
5
6
7
8
9
10
|
#include "ns.h"
#include <iostream>
using namespace std;
using namespace ns; // 导入整个ns命名空间
int main() {
cout << a << endl; // 直接使用ns::a
cout << f(8) << endl; // 直接使用ns::f()
return 0;
}
|
1
2
3
4
5
6
|
//一:导入整个名字空间
using namespace ns;
//二:导入名字空间中指定的符号
using ns::a;
using ns::f;
|
如果使用某个命名空间时,仅使用到少量符号的话,如果导入整个名字空间,会导致大量未被使用的符号,会造成冲突,会造成名字空间污染。
进阶
C++ 支持嵌套定义命名空间,也就是在一个命名空间内部再定义另一个命名空间。
1
2
3
4
5
6
7
8
9
10
|
#include "ns.h"
namespace ns {
int a = 1; // 外层变量定义
namespace nested_ns {
int a = 2; // 内层变量定义
int x = 100; // 内层变量定义
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#ifndef NS_H
#define NS_H
namespace ns {
extern int a; // 外层变量声明
namespace nested_ns {
extern int a; // 内层变量声明
extern int x; // 内层变量声明
}
}
#endif
|
扩展性
当程序在多处定义了相同的名字空间时,它们将会融合成一个统一的作用域
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#include <iostream>
#include "ns.h"
// 扩展命名空间ns,新增变量b
namespace ns {
int b = 666;
}
using namespace std;
using namespace ns;
int main(void) {
cout << a << endl; // 输出1
cout << b << endl; // 输出666
return 0;
}
|
全局作用域
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
#include <iostream>
using namespace std;
// 全局变量
int global = 100;
int main()
{
// 局部同名变量
int global = 200;
// 1. 直接访问:优先局部,输出200
cout << global << endl;
// 2. 加::访问:强制全局,输出100
cout << ::global << endl;
return 0;
}
|
全局作用域的名字空间是匿名的,引用全局作用域符号只需加 :: 即可。