C/C++ 多文件编译笔记
 
 
 
 
 
 
 
 
 
 
 
贡献者: addis
以下规则对 c 和 c++ 语言都适用。
1. 单个 translation unit
-
#include
头文件(.h)相当于直接把头文件的内容插入到当前位置。
- 头文件可以没有或者有任意后缀名(例如标准库的头文件就没有后缀名)。
- 每个 .cpp(也可以用 .cxx)文件叫做一个 translation unit。可以单独编译成一个 object 文件(.o)
- 某个 translation unit 中定义的宏只在这一个 translation unit 中有效,即从定义开始到文件底部(或者到
#undef
)。
- 头文件开始用
#pragma once
可以防止同一个头文件被多次插入同一个 translation unit。例如 b.h
和 c.h
中都 include 了 a.h
,如果 cpp 文件中同时 include 了 b.h
和 c.h
,a.h
就不会被插入两次。注意这并不是 C++ 标准,但大部分编译器都实现了。
2. 多个 translation unit
- 若有多个 translation unit,可以分别编译,然后将所有 object 文件 link 起来就成了可执行程序。
- 一个 translation unit 中定义的函数要在另一个 translation unit 调用前要先声明(declare)。
- 每个 translation unit 编译的时候也不需要有其他 translation unit 存在,即使调用了其他 translation unit 中定义的函数。
- 只有在 link 阶段编译器才会检查一个 o 文件中调用的函数是否能在另一个 o 文件中有定义,如果没有,link 就会失败。
- ODR(one definition rule) 要求一个函数不能在同一个或不同 translation unit 中有重复的定义(definition),例如全局变量和函数(包括成员函数)。但重复的声明(declaration)是允许的。
- inline 函数或变量需要在使用到它的每个 translation unit 中都有一样的定义(所以一般放到头文件中)。否则即使预先 declare 也会出错。
- C++17 开始支持
inline
的全局变量,这相当于在一个 TU 中定义,其他 TU 中声明,这样就可以在头文件中定义全局变量。
-
class
的声明也需要在使用到它的每个 translation unit 中都有一样的定义(所以一般放到头文件中)。
- 任何函数或类的 template 的定义同样也需要在使用到它的每个 translation unit 中都有一样的定义(所以一般放到头文件中)。
-
inline
的含义已经与是否真的 inline
几乎无关了,只是为了避免 ODR 错误的一种手段。
- 即使使用了
inline
,同一个 translation unit 中也不可以出现两个同样的定义。
- 如果一个函数调用的函数在它之后定义,则需要将 declaration 放在它前面。
- 所以编译时若提示找不到某个函数,一定要注意是 compile 过程中没找到还是 link 过程中没找到。如果是后者可能是没有 link 到适当的库(
-l
选项)。无论是静态还是动态库,就相当于是编译好的 .o 文件打包好。
- 另一个避免 ODR 的方法是用
static
关键词让其具有 internal linkage。这样它就只在当前的 TU 中生效,linker 看不见它。这样就可以在不同 TU 中给同名函数或变量用不同的定义。这(有点)相当于不用 static
,但命名成不同的变量或函数。如果制作成 .a
或者 .so
库,使用者同样也不能用它们。
-
const
的全局变量可以放在头文件中,同样具有 local linkage,在每个 TU 中都有一个独立的对象,不违反 ODR。
致读者: 小时百科一直以来坚持所有内容免费无广告,这导致我们处于严重的亏损状态。 长此以往很可能会最终导致我们不得不选择大量广告以及内容付费等。 因此,我们请求广大读者
热心打赏 ,使网站得以健康发展。 如果看到这条信息的每位读者能慷慨打赏 20 元,我们一周就能脱离亏损, 并在接下来的一年里向所有读者继续免费提供优质内容。 但遗憾的是只有不到 1% 的读者愿意捐款, 他们的付出帮助了 99% 的读者免费获取知识, 我们在此表示感谢。
 
 
 
 
 
 
 
 
 
 
 
友情链接: 超理论坛 | ©小时科技 保留一切权利