C++头文件(.h)和实现文件(.cpp)区别
Resource Files 资源文件夹 *.ico *.bmp
Source Files 源文件 *.cpp *.c
Header Files 头文件 *.h
头文件
头文件的所有内容,都必须包含在
#define {Filename}
// {Content of head file}
#endif
头文件中的 #ifndef/#define/#endif 防止该头文件被重复引用
指一个头文件在同一个cpp文件中被include了多次,这种错误常常是由于include嵌套造成的。
比如:存在a.h文件#include "c.h"而此时b.cpp文件导入了#include "a.h" 和#include "c.h"此时就会造成c.h重复引用。
头文件被重复引用引起的后果:
有些头文件重复引用只是增加了编译工作的工作量,不会引起太大的问题,仅仅是编译效率低一些,但是对于大工程而言编译效率低下那将是一件多么痛苦的事情。
inline限定符
在头文件中,可以对函数用inline限定符来告知编译器,这段函数非常的简单,可以直接嵌入到调用定义之处。
当然inline的函数并不一定会被编译器作为inline来实现,如果函数过于复杂,编译器也会拒绝inline。
因此简单说来,代码最好短的才作为inline。有循环,分支,递归的函数都不要用做inline。
对于在类定义内定义实现的函数,编译器自动当做有inline请求(也是不一定inline的)。因此在下边,我把带有inline限定符的函数成员和写在类定义体内的函数成员统称为“要inline的函数成员”
非模板类型
全局类型
就像前面笼统的话讲的:申明写在.h文件。
对于函数来讲,没有实现体的函数,就相当于是申明;而对于数据类型(包括基本类型和自定义类型)来说,其申明就需要用extern来修饰。
然后在.cpp文件里定义、实现或初始化这些全局函数和全局变量。
自定义类型
对于自定义类型,包括类(class)和结构体(struct),它们的定义都是放在.h文件中。其成员的申明和定义就比较复杂了,不过看下面的表格,还是比较清晰的。
函数成员
函数成员无论是否带有static限定符,其申明都放在.h文件的类定义内部。
对于要inline的函数成员其定义放在.h文件;其他函数的实现都放在.cpp文件中。
数据成员
数据成员的申明与定义都是放在.h文件的类定义内部。对于数据类型,关键问题是其初始化要放在什么地方进行。
对于只含有static限定符的数据成员,它的初始化要放在.cpp文件中。因为它是所有类对象共有的,因此必须对它做合适的初始化。
对于只含有const限定符的数据成员,它的初始化只能在构造函数的初始化列表中完成。因为它是一经初始化就不能重新赋值,因此它也必须进行合适的初始化。
对于既含有static限定符,又含有const限定符的数据成员,它的初始化和定义同时进行。它也是必须进行合适的初始化
对于既没有static限定符,又没有const限定符的数据成员,它的值只针对本对象可以随意修改,因此我们并不在意它的初始化什么时候进行。
对C++编译器而言,当调用函数的时候,编译器只需要看到函数的声明。当定义类类型的对象时,编译器只需要知道类的定义,而不需要知道类的实现代码。因此,因该将类的定义和函数声明放在头文件中,而普通函数和类成员函数的定义放在源文件中。
模板类型
模板定义很特殊。由template<…> 处理的任何东西都意味着编译器在当时不为它分配存储空间,它一直处于等待状态直到被一个模板实例告知。在编译器和连接器的某一处,有一机制能去掉指定模板的多重定义。所以为了容易使用,几乎总是在头文件中放置全部的模板声明和定义。
只有模板被具体化(specialization)之后(用在特定的类型上),编译器才会根据具体的类型对模板进行编译。
所以才定义模板的时候,会发现编译器基本不会报错,也做不出智能提示。
因为模板的这种特殊性,它并没有自己的准确定义,因此我们不能把它放在.cpp文件中,而要把他们全部放在.h文件中进行书写。这也是为了在模板具体化的时候,能够让编译器可以找到模板的所有定义在哪里,以便真正的定义方法。
至于模板类函数成员的定义放在哪里,建议放在类定义之外,因为这样当你看类的时候,一目了然地知道有那些方法和数据;但是用Visual Studio的时候查看到其标准库的实现,都是放在类内部的。
概览区别(两者分别包含哪些内容 )
| 头文件(.h) |
|
||
| 实现文件夹(.cpp) |
|
再介绍一个.hpp:
.hpp其实质就是将.cpp的实现代码混入.h头文件当中,定义与实现都包含在同一文件,则该类的调用者只需要include该hpp文件即可,无需再 将cpp加入到project中进行编译。而实现代码将直接编译到调用者的obj文件中,不再生成单独的obj,采用hpp将大幅度减少调用 project中的cpp文件数与编译次数,也不用再发布烦人的lib与dll,因此非常适合用来编写公用的开源库。

浙公网安备 33010602011771号