回复至:小白问题:关于Cpp代码规范性 .h与.cpp文件的关系与内容的存疑

孙锡源
  • 文章数量: 704
@ibadboy

我个人已经很多年不写C++了,以下内容只保证总体上正确:

编译器如何寻找h文件对应的cpp文件

这个涉及到C++编译器的编译过程:

  1. 预处理
  2. 编译
  3. 链接

在预处理阶段,所有使用include宏标记的内容都会被原封不动的复制到当前文件中。

比如说以下代码:

include "hello.h"
  
int main()
{
        hello();

        return 0;
}

经过预处理后会变成这样:

int main();

int main() { 
    hello(); 
    return 0; 
}

可以发现,其实根本不存在所谓的“h文件与cpp文件关联”,因为h文件根本就是等于不存在,在预处理过程中它就会被全部复制到引用它的cpp中。

关于include宏的介绍见GCC官方文档:https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html

在其后的编译过程中,每个cpp文件会被单独编译,并各自生成二进制文件。如果你没在每个cpp文件头部声明要引用的类、函数的定义,则这个阶段就会抛出函数、类未定义的错误。

最后的链接过程可以理解成是将多个编译后的cpp文件关联成一个整体,对于在同一个命名空间和作用域中的函数、类、变量,其链接后就是全局公用的。在这个阶段如果函数的逻辑部分未发现的话g++编辑器会抛出错误。

常见.h的格式是什么样的

如果你的代码不包含对外提供的接口的话可以不写h文件,而是使用extern关键字声明该函数、变量、类在此cpp文件外部定义。

当然,不怕麻烦的话给每个cpp文件写一个h文件也可以,或者也可以把多个cpp文件的定义塞到一个h文件里。

如果有一些全局配置信息的话可以写一个类似config.h这种文件,其中只包含一些常量的定义,就好像WordPress的wp-config.php一样。

防止重复编译

在Linux内核中多使用以下宏来避免重复包含:

#ifndef FOOP_H
#define FOOP_H
int foo(int a);
#endif

比如这个关于ECC加密算法的头文件:

https://github.com/torvalds/linux/blob/master/include/crypto/ecc_curve.h

来自, 香港, 中国