为什么 C++ 模板只能写在一个文件里?
why-cpp-templates-only-be-written-in-onefile
在一般的 C++ 开发中,习惯将函数声明与实现放在不同的文件中,如声明放在
.h
文件,实现放在
.cpp
文件,并在其它地方引用时只包含
.h
文件。但对于 C++ 的模板,这是一个例外,它只能被写在一个文件中。
普通函数
// test.h
int sumInt(int a, int b);
// test.cpp
int sumInt(int a, int b) {
return a + b;
模板函数
// test.cpp
template<typename T>
T sum(T a, T b) {
return a + b;
编译阶段
要理解为什么这样,需要先了解 C++ 的编译、链接过程。首先要知道的是,每个
.cpp
文件会被独立编译为对应的
.obj
文件,这个文件是
.cpp
文件的二进制汇编版本。
但随着模块化设计的发展,可能会出现一个文件调用另一个文件函数的情况,由于独立编译的缘故,这些函数的地址不能被确定,因此生成的
CALL
指令跟随的是一个虚拟函数地址。
链接阶段
当整个编译过程结束后,开始链接流程。即将所有的
.obj
文件链接为对应操作系统的可执行文件,如 Windows 的
.exe
文件。在这个过程中,真实的函数地址才得以确定。
简单来说,编译期间不会检查函数是否实现,它只需要函数的声明。但在链接时,要处理函数间的调用关系,此时才会检查函数的具体实现。
模板的困境
由于 C++ 的模板原理是根据调用方参数类型,生成多个不同的实现。如
sum(1, 2);