一、头文件(.h)
1、作用:用于存储函数、变量、类、宏等声明的文件。提供接口声明,供其他源文件使用。
2、格式:在写头文件时需注意,在开头和结尾处需按下列格式加上预编译语句(如下):
#ifndef Unit1H
#define Unit1H
// 你的代码写在这里
#endif
规定格式是为了防止重复编译,不按照格式来可能会出问题。
头文件的所有内容,都必须包含在格式里面,这样才能保证头文件被多个其他文件引用(include)时,内部的数据不会被多次定义而造成错误
Unit1H可以修改,叫什么都行,只要符合命名规范。原则上说,建议与头文件的名字相对应,方便阅读,毕竟 '程序是为程序员写的' 。
3、解析过程:
头文件的解析过程可以分为以下几个步骤:
- 预处理(Preprocessing):在编译器对源文件进行编译之前,会对头文件进行预处理。预处理器(Preprocessor)会将头文件中的宏、include 指令等展开,并将其包含到源文件中。
- 包含(Inclusion):当源文件包含头文件时,预处理器会将头文件的内容拷贝到源文件中。这个过程称为包含(Inclusion)。
- 解析(Parsing):编译器会对头文件中的声明进行解析,检查语法正确性,并将其转换为中间代码(Intermediate Code)。
- 链接(Linking):在编译器对源文件进行编译时,会将头文件中的声明与源文件中的定义链接起来,生成可执行文件。
4、优点
- 提高代码重用性:头文件可以将公共的函数、变量、类等声明集中到一起,供多个源文件使用。
- 提高代码可读性:头文件可以将接口声明与实现分离,使得代码更加清晰易懂。
- 提高编译速度:头文件可以减少编译时间,因为编译器只需要编译头文件一次。
二、源文件(.cpp)
1、作用:用于存储程序的实现代码。主要写 实现头文件中已经声明的那些函数的具体代码。
2、格式:引用需要的头文件和自身函数声明的头文件
#include "Unit1.h " //自身声明函数的头文件
//这里没用到其他的头文件,所以没加
Unit1::Unit1() //实现需求的函数
{
this->r=5.0;
}
Unit1::Unit1 double R) //实现需求的函数
{
this->r=R;
}
double Unit1:: Area() //实现需求的函数
{
return 3.14*r*r;
}
注意:开头处包含了Unit1.h,非常建议.cpp文件与头文件相对应,即 Unit1.cpp。事实上,Unit1.cpp这个文件的名字其实不一定要叫Unit1.cpp,但是于头文件相对应很容易让程序员理解。
3、解析过程:
- 预处理(Preprocessing):在编译器对源文件进行编译之前,会对源文件进行预处理。预处理器(Preprocessor)会将源文件中的宏、include 指令等展开,并将其包含到源文件中。
- 词法分析(Lexical Analysis):编译器会对源文件进行词法分析,将源文件中的字符流转换为Token流。Token是编译器的基本单元,例如关键字、标识符、操作符等。
- 语法分析(Syntax Analysis):编译器会对Token流进行语法分析,检查源文件中的语法正确性,并将其转换为抽象语法树(Abstract Syntax Tree,AST)。
- 语义分析(Semantic Analysis):编译器会对AST进行语义分析,检查源文件中的语义正确性,并将其转换为中间代码(Intermediate Code)。
- 优化(Optimization):编译器会对中间代码进行优化,以提高代码的执行效率。
- 目标代码生成(Code Generation):编译器会将中间代码转换为目标代码(Object Code),即机器语言。
- 链接(Linking):编译器会将目标代码与库文件等链接起来,生成可执行文件(Executable File)。
4、优点
- 源文件可以将程序的实现代码集中到一起,易于维护和修改。
- 源文件可以将公共的函数、变量、类等定义集中到一起,供多个程序使用。
- 源文件可以提高代码的可读性和可维护性。
三、细节说明
(1)Unit1.h 叫做头文件,它是不能被编译的。
#include 叫做编译预处理指令,可以简单理解成:在 Unit1.cpp 中的 #include "Unit1.h" 指令把 Unit1.h 中的代码在编译前添加到了 Unit1.cpp 的头部。
每个.cpp文件会被编译,生成一个.obj文件,然后所有的.obj文件链接起来你的可执行程序就算生成了。
(2)在.h文件中严格区分声明语句和定义语句。
(3).h和.cpp具有同样的主文件名的情况呢,对编译器来讲是没有什么意义的,编译器不会去匹配二者的主文件名,相反它很傻,只认#include等语句。
(4)在h文件中声明,在cpp文件中定义。
“声明”向计算机介绍名字,即,“这个名字是什么意思”。“定义”为这个名字分配存储空间。
无论涉及到变量时还是函数时含义都一样。无论在哪种情况下,编译器都在“定义”处分配存储空间。对于变量,编译器确定这个变量占多少存储单元,并在内存中产生存放它们的空间。对于函数,编译器产生代码,并为之分配存储空间。函数的存储空间中有一个由使用不带参数表或带地址操作符的函数名产生的指针。定义也可以是声明。如果该编译器还没有看到过名字A,程序员定义int A,则编译器马上为这个名字分配存储地址。声明常常使用于extern关键字。如果我们只是声明变量而不是定义它,则要求使用extern。对于函数声明, extern是可选的,不带函数体的函数名连同参数表或返回值,自动地作为一个声明。
非模板类型(none-trmplate) | 模板类型(trmplate) | |
头文件(.h) |
|
|
|
| |
源文件(.cpp) |
|
|
|