第6.7章: 翻译单元

English

概述

C++ 程序常被拆分到多个文件中。每个文件被单独编译成一个翻译单元, 然后由链接器把所有翻译单元合并成最终的可执行文件。

现代 C++ 还引入了模块,它是被编译的翻译单元, 可以取代许多头文件的使用场景。

在本章中,你将学到:

1. 什么是翻译单元?

翻译单元是对单个 .cpp 文件应用预处理器 (#include、#define 等)后得到的结果, 也就是编译器真正去编译的那一个大文件。


main.cpp        → translation unit A
math.cpp        → translation unit B
io.cpp          → translation unit C

每个翻译单元被独立编译成一个目标文件:


main.cpp  → main.o
math.cpp  → math.o
io.cpp    → io.o

然后链接器把所有目标文件合并成一个可执行文件。

2. 声明 vs. 定义

处理多个翻译单元时,把声明与定义分开 至关重要。

声明放在头文件(.hpp)中。 定义放在源文件(.cpp)中。


// math.hpp (declaration)
int square(int x);

// math.cpp (definition)
int square(int x)
{
    return x * x;
}

// main.cpp
#include "math.hpp"

int main()
{
    ::fast_io::io::println(square(5));
}

3. 编译多个文件

你可以在一条命令中编译并链接多个翻译单元:


clang++ -std=c++23 main.cpp math.cpp -o program

或者用 g++:


g++ -std=c++23 main.cpp math.cpp -o program

也可以分别编译每个翻译单元,之后再链接:


clang++ -std=c++23 -c main.cpp   # produces main.o
clang++ -std=c++23 -c math.cpp   # produces math.o
clang++ main.o math.o -o program

4. 模块作为翻译单元

C++ 模块接口文件(.cppm)同样是一个翻译单元。 模块不使用 #include 复制文本,而是用 export 与 import 共享已编译的 声明。


math.cppm  → translation unit (module interface)
main.cpp   → translation unit (imports the module)

编译器从模块接口生成 PCM(预编译模块), 其他翻译单元再导入它。

5. 编写并编译一个简单模块

模块接口声明一个模块,并导出你希望其他翻译单元 使用的函数或类型。


// math.cppm — module interface
export module math;

export int square(int x)
{
    return x * x;
}

另一个翻译单元可以导入该模块:


// main.cpp
import math;
import fast_io;

int main()
{
    ::fast_io::io::println(square(7));
}

用 Clang 编译模块

第 1 步 —— 编译模块接口


clang++ -std=c++26 --precompile math.cppm -o math.pcm

第 2 步 —— 编译你的程序并导入 PCM


clang++ -std=c++26 -fmodule-file=math=math.pcm -c main.cpp -o main.o

第 3 步 —— 链接最终可执行文件


clang++ main.o -o program

可选:编译 fast_io 模块


clang++ -std=c++26 --precompile \
  $HOME/libraries/fast_io/share/fast_io/fast_io.cppm \
  -I$HOME/libraries/fast_io/include \
  -o fast_io.pcm

clang++ -std=c++26 \
  -fmodule-file=math=math.pcm \
  -fmodule-file=fast_io=fast_io.pcm \
  -c main.cpp -o main.o

clang++ main.o -o program

要点