.cpp文件和.h文件有什么区别?


70

因为我已经制作了.cpp文件,然后将它们传输到.h文件,所以我能找到的唯一区别是您不能#include .cpp文件。我缺少什么区别吗?


2
要理解下面人们的回答,您可能需要问另一个问题:即“ C ++中的“声明”和“定义”之间有什么区别?”
ChrisW

1
我知道声明和定义之间的区别。

3
您可以包含任何所需内容,但是如果将全局变量包含到多个编译单元中,则链接阶段将会中断。这就是为什么有约定不链接.cpp文件的原因。
约翰·史密斯,

Answers:


67

C ++生成系统(编译器)没有区别,所以这只是惯例之一。

习惯上,.h文件是声明,.cpp文件是定义。

这就是为什么.h文件被#include的原因-我们包括了声明。


C ++构建系统确实有所区别-例如,尝试在.h文件和.cpp文件上运行g ++,然后看看会发生什么。

我知道.cpp文件(大多数情况下)用于定义在.h文件中声明的函数/类/ etc,但是您也可以在.h文件中定义变量。

5
@Neil Butterworth:是的,G ++编译器理解该约定,但是您可以通过强制使用该语言来进行编译。
马丁·约克

26

.cpp文件是编译单元:这是将要编译的真实源代码文件(在C ++中)。

.h(头文件)文件实际上是将被复制/粘贴到出现#include precompiler指令的.cpp文件中的文件。将标头代码插入.cpp代码后,即可开始.cpp的编译。


1
为什么说.cpp文件而不是.cpp文件?

12
@ Keand64:因为编译器在编译时一次只查看一个.cpp文件。它读取一个.cpp文件,读取所有#included .h文件,编译整个程序,编写一个.o(或.obj)文件,然后继续执行下一个.cpp文件。
格雷格·希吉尔

这是否意味着.cpp和.h必须具有相同的名称?
Fathergorry'2

@fathergorry不,没有命名源文件(没有标题)的规则,只有约定。
克莱姆

14

标头(.h,,.hpp...)文件包含

  • 类定义(class X { ... };
  • 内联函数定义(inline int get_cpus() { ... }
  • 函数声明(void help();
  • 对象声明(extern int debug_enabled;

源文件(.c.cpp.cxx)包含

  • 函数定义(void help() { ... }void X::f() { ... }
  • 对象定义(int debug_enabled = 1;

但是,实际上不需要标头以.h后缀命名和源文件以后缀命名的约定.cpp。总是可以告诉一个好的编译器如何处理某个文件,而不管其文件名后缀如何(-x <file-type>对于gcc。Like -x c++)。

源文件将包含在整个程序中只能出现一次的定义。因此,如果在某处包含一个源文件,然后将该文件的编译结果与该源文件本身的编译结果链接在一起,则当然会出现链接器错误,因为这些定义现在出现两次:包含源文件,然后在包含它的文件中。这就是为什么您在包含.cpp文件时遇到问题。


12

我知道声明和定义之间的区别。

鉴于:

  • CPP文件包含它包含的任何标头中的定义(因为CPP和标头文件一起成为一个“翻译单元”)
  • 一个以上的CPP文件可能包含一个头文件
  • 链接器通常不喜欢在多个CPP文件中定义的任何内容

因此,头文件中的任何定义都应为内联或静态。头文件还包含多个CPP文件使用的声明。

既不是静态的也不是内联的定义放置在CPP文件中。同样,通常仅将一个CPP文件中需要的任何声明放置在该CPP文件本身中,而不是放置在任何(可共享的)头文件中。


9

.h文件或头文件用于在类声明中列出可公开访问的实例变量和方法。.cpp文件或实现文件用于实际实现那些方法并使用那些实例变量。

它们分开的原因是因为.h文件没有被编译成二进制代码,而.cpp文件却被编译成二进制代码。以图书馆为例。假设您是作者,并且不希望它是开源的。因此,您可以将编译后的二进制库和头文件分发给客户。这样一来,他们可以轻松查看有关可以使用的库类的所有信息,而无需查看如何实现这些方法。它们更适合使用您的代码而不是编译器的人们。如前所述:这是惯例。


我知道他没有问为什么,但这对我来说是最有用的答案。了解为什么会更容易将逻辑连接到细节
vampiire 20-4-17

3

一个好的经验法则是“ .h文件应该有[可能]被多个源文件使用的声明,但没有代码可以运行。”


所以我想.h类似于C#接口
Hugo Nava Kopp

2

其他人已经提供了很好的解释,但是我认为我应该澄清各个扩展之间的区别:

  C的源文件:.c
  C的头文件:.h

  C ++的源文件:.cpp
  C ++的头文件:.hpp

当然,正如已经指出的那样,这些只是约定。编译器实际上并不关注它们-纯粹是为了编码者的利益。


6
实际上,大多数人也将.h用于C ++。
Zifre

@Zifre:是的,因此,尽管很多人可能不遵循这些约定,但我还是建议使用这些命名约定
诺多林

1

按照惯例,.h文件包含在其他文件中,并且它们本身不能直接编译。再次,.cpp文件是-按照惯例-编译过程的根源;它们直接或间接包含.h文件,但通常不包含.cpp文件。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.