C++ 关于.h文件和.cpp文件的知识梳理(1)
1. C++程序的编译过程
C++程序的编译过程可以分为四个步骤,分别为预处理, 编译,汇编,链接。他们的工作内容分别为:
- 预处理:展开头文件,去除源代码中的注释等。
- 编译: 将预处理后的程序转换成汇编代码。
- 汇编: 将汇编代码进一步转换成二进制机器码。
- 链接:将多个目标文件及其所需的库文件链接生成可执行文件。
其中我们关注最多的是 预处理 和 链接,头文件和预处理息息相关,而声明与定义的分离则和链接有着密切关系。
2. #pragma once 有什么作用
我们都知道 #pragma once 还有类似" #ifndef “、” #endif "的作用都是保护你的头文件只被目标文件加载一次,但这个保护的作用能有多大呢?首先我们需要知道头文件的作用,#include 一个文件(无论.h或是.cpp),仅仅是将文件中的代码复制一份到你的代码之中,头文件(.h)仅在编译过程中的预处理中起到作用。 知道了这个后我们便可以开始进行一些测试了。
测试样例一
代码:
//head.h
int a = 10;
//main.cpp
#include <iostream>
#include "head.h"
#include "head.h"//重复导入
int main()
{
std::cout<<"a = "<<a<<std::endl;
std::cout<<"a's address = "<<&a<<std::endl;
return 0;
}
执行结果:
In file included from C:head.h:2:5: error: redefinition of 'int a'
int a = 10;
^
In file included from C:head.h:2:5: note: 'int a' previously defined here
int a = 10;
结果报错了,编译器提示错误,重复定义了int a变量,这是因为我们#include “head.h” 两次,相当于在我们的main.cpp中加了两行int a = 10 。我们在head.h文件中加上#pragma once 可以再运行试试。
//head.h
#pragma once
int a = 10;
//main.cpp
内容不变
执行结果:
a = 10
a's address = 0x40a010
程序编译通过了,因为#pragma once 让头文件只被导入了一次,但一个头文件往往不止会被一个源文件include,也有可能被多个文件include,到时候我们的写法还对吗?#pragma once 还能保证我们的程序安全,不会产生重复定义吗?我们来看接下来的示例。
测试样例2
代码:
//head.h
#pragma once
#