命名空间
封闭取值的类型有了,工程里还会遇到另一类组织问题:不同模块出现同名实体,调用处需要分清一个名字来自哪个分组。命名空间把相关的常量、类型和函数收在一个名字下。本章在 枚举类 的类型手段之外补上这一分组手段。
同名常量
命名空间用限定名区分同名实体,片段里的两个 kSize 互不冲突:
片段:同名常量放在不同命名空间
namespace board {
constexpr int kSize{3};
}
namespace config {
constexpr int kSize{16};
}
// 访问时写 board::kSize 与 config::kSize,两个同名常量互不冲突限定名说明了值来自哪个分组,同一工程的不同模块因此可以各自拥有同名实体。完整示例把两个分组放进一个程序并分别输出:
namespaces.cpp
// 命名空间示例:同名常量放在不同命名空间并分别输出。
#include <iostream>
namespace board {
constexpr int kSize{3};
}
namespace config {
constexpr int kSize{16};
}
int main() {
std::cout << "棋盘尺寸: " << board::kSize << "\n";
std::cout << "配置尺寸: " << config::kSize << "\n";
return 0;
}分组约定
项目代码把同一游戏的类型收进一个命名空间,如井字棋值类型定义在 tictactoe 命名空间中:
- 常量名按约定用
k加大驼峰,头文件里供多个.cpp共享的常量还要加inline,写法见 constexpr; - 命名空间本身用小写加下划线命名,名字表达分组的内容,不表达“utils”“helpers”这类笼统职责。
常见错误
在头文件里写 using namespace
using namespace board; 会把整个分组的名字倒进包含它的文件,同名实体重新变得难以分辨:
- 头文件被多处包含时影响面更大,头文件里不要写;
- 需要频繁使用某个分组时,把
using限定在.cpp文件内部,或直接写限定名。
自测问题
先不要展开答案,试着自己把回答完整说出来,再展开对照。说不出来的部分,回到对应小节对照正文。
命名空间解决什么问题?
查看答案
它把相关的名字分组,避免不同模块的同名实体冲突,调用处用限定名选择具体分组。
为什么头文件里不写
using namespace?查看答案
它把整个分组的名字倒进包含它的文件,同名冲突重新出现。头文件被多处包含时影响面最大,需要时把
using限定在.cpp内部。
本章回顾
你现在能用命名空间给名字分组,用限定名区分同名实体。完整示例见 namespaces.cpp,下一章用 struct 把相关的数据组合成值类型。