一、名字空间 namespace
1.1 为什么需要名字空间?
核心作用:解决命名冲突;解决 C 语言全局变量、全局函数命名冲突问题,将代码分组隔离,不同空间内的同名标识符互不干扰,相当于给代码添加专属“作用域前缀”;注意:不改变变量的生命周期、存储位置,只是从名字做了隔离;
生活化类比:同一个文件夹里,不能有两个同名的文件;但放在不同文件夹里,同名文件就可以共存,用文件夹路径区分即可。
对应到代码:如果两个程序员都写了同名的函数、变量、类放在一起编译就会报重定义错误。
1.2 什么是名字空间?
1.2.1 名字空间定义
namespace 空间名字 {
// 里面可以放:变量、函数、类、结构体、另一个名字空间(名字空间嵌套)
int num = 0;
void func() {/* … */}
class Student {/*…*/}
}
/*
名字空间的大括号后面不用加分号(和类不一样);
同一个名字空间可以分开写多次,甚至跨文件写,编译器会自动把它们合并成一个;
名字空间只能定义在全局范围,或者另一个名字空间内部,不能写在函数里面
*/
1.2.2 访问语法
空间名::成员名。:: 为作用域解析符,释义为“的”。
1.3 怎样用名字空间?——三种访问方式
1.3.1 全前缀访问(最规范、最安全、推荐正式项目用)
// 直接写 空间名::成员名,明确指定来自哪个名字空间
A::num = 20;
A::func();
1.3.2 单个成员引入
// 用 using 空间名::成员名; 声明之后,这个成员就可以直接用名字访问了。
using A::num; // 只把 A 里的 num 放出来
num = 30; // 等价于 A::num = 30;
1.3.3 整个名字空间展开(练习/小项目使用)
// 用 using namespace 空间名;,把这个名字空间里的所有东西全部放到全局作用域,之后可以直接写名字调用。
using namespace A;
num = 40; // 直接用
func(); // 直接用
1.3.4 最常用的名字空间:std
C++ 标准库提供的所有功能——cout、cin、string、endl、vector 等等,全部都放在 std 这个名字空间里。这么设计的原因就是避免冲突:标准库有几百个名字,如果都放在全局,很容易和你自己写的变量、函数重名。放进 std 里,默认不会和你的代码冲突,需要用的时候再展开或者加前缀。
1.3.5 三种方式对比

1.3.6 延伸知识
同名空间自动合并:多次定义同名空间,内容自动追加,不会覆盖;
名字空间起别名:如果名字空间的名字太长,可以给他起个短别名;
namespace CG = China::Guangdong;
cout << CG::city << endl; // 和 China::Guangdong::city 效果一样
空间嵌套:支持多层嵌套。通过多级 :: 访问,类似文件夹分层。
namespace China {
namespace Guangdong {
string city = "深圳";
}
}
// 访问方式:逐层加 ::
cout << China::Guangdong::city << endl;
匿名空间:无名称的空间,内部内容仅当前文件可用,替代 C 语言 static 全局限定。
namespace {
int file_only = 100;
}
二、名字空间声明 VS 名字空间指令
2.1 名字空间声明
语法:using 命名空间名::成员名
核心作用:精准引入命名空间中单个指定成员,将该名字直接写入当前作用域的定义表,属于高优先级名字。
2.2 名字空间指令
语法:using namespace 命名空间名;
核心作用:批量引入命名空间所有成员变量,仅将名字加入当前作用域的可见表,不会写入当前作用域的定义表,属于低优先级名字;
// 名字空间声明 和 名字空间指令 的差别
#include <iostream>
using namespace std;
namespace ns1 {
int g_value = 0;
int g_other = 0;
}
namespace ns2 {
int g_value = 0;
int g_other = 0;
}
int main(void) {
// 名字空间指令:将 ns1 所有成员引入当前作用域(低优先级,属于“可见”级别)
using namespace ns1;
// 名字空间声明:仅将 ns2::g_value 引入当前作用域(高优先级,属于“定义”级别)
using ns2::g_value;
g_value = 666; // 优先匹配 名字空间声明 的 ns2::g_value
cout << "ns1::g_value=" << ns1::g_value << ", ns2::g_value=" << ns2::g_value << endl;
g_other = 999; // 仅 ns1 通过指令批量引入,因此匹配 ns1::g_other
cout << "ns1::g_other=" << ns1::g_other << ", ns2::g_other=" << ns2::g_other << endl;
return 0;
}
三、代码实战
#include <iostream>
using namespace std;
// 基础命名空间
namespace ns1 {
int g_value = 10;
int g_other = 20;
}
namespace ns2 {
int g_value = 30;
int g_other = 40;
}
// 嵌套命名空间演示
namespace outer_ns {
int num = 100;
namespace inner_ns {
int num = 200;
}
}
int main(void) {
// 1. 优先级验证:单个声明 > 批量指令
cout << "===== 1. 优先级验证 =====" << endl;
{
using namespace ns1;
using ns2::g_value;
g_value = 666; // 优先匹配 ns2::g_value
g_other = 999; // 匹配批量引入的 ns1::g_other
cout << "ns1::g_value = " << ns1::g_value << endl;
cout << "ns2::g_value = " << ns2::g_value << endl;
cout << "ns1::g_other = " << ns1::g_other << endl;
cout << "ns2::g_other = " << ns2::g_other << endl;
}
// 2. 批量引入两个命名空间:同名变量产生二义性(取消注释会编译报错)
cout << "\\n===== 2. 二义性冲突演示 =====" << endl;
/*
{
using namespace ns1;
using namespace ns2;
g_value = 100; // 编译错误:g_value 指代不明确
// 必须显式指定命名空间才能正常使用
ns1::g_value = 100;
ns2::g_value = 200;
}
*/
// 3. using 的局部作用域
cout << "\\n===== 3. using 局部作用域 =====" << endl;
{
using ns1::g_value;
g_value = 111; // 仅在当前代码块内有效
cout << "块内 ns1::g_value = " << ns1::g_value << endl;
}
ns1::g_value = 222; // 出块后 using 失效,必须显式指定命名空间
cout << "块外 ns1::g_value = " << ns1::g_value << endl;
// 4. 命名空间别名(简化长命名空间书写)
cout << "\\n===== 4. 命名空间别名 =====" << endl;
namespace inner = outer_ns::inner_ns;
cout << "嵌套命名空间值 = " << inner::num << endl;
return 0;
}
3.1 核心疑问解答:g_value 为何不冲突报错?
代码中 ns1 和 ns2 均存在 g_value,但 g_value = 666; 不会报歧义错误,核心原因是两者名字查找优先级不同,不在同一竞争层级:
- 高优先级(using 声明):using ns2::g_value 将名字写入 main 当前作用域定义表,编译器优先查找该层级
- 低优先级(using 指令):using namespace ns1 仅将名字加入可见表,不参与当前作用域优先级竞争
C++ 查找铁律:名字从内到外、从高优先级到低优先级查找,找到第一个匹配项立即终止查找。因此编译器优先匹配到 ns2::g_value,直接忽略 ns1::g_value,无歧义、不报错。
3.2 g_other 赋值逻辑说明
代码中无任何针对 g_other 的 using 声明,当前作用域定义表无匹配名字,编译器降级查找可见表,最终匹配到 ns1::g_other,因此赋值 999 生效于 ns1 的成员。
3.3 高危报错

3.4 C++ 名字查找优先级
局部变量 > 当前作用域 using 声明 > 外层作用域变量 > using 指令引入的成员




