.cpp 文件和 .h 文件有啥区别?

Posted

技术标签:

【中文标题】.cpp 文件和 .h 文件有啥区别?【英文标题】:What is the difference between a .cpp file and a .h file?.cpp 文件和 .h 文件有什么区别? 【发布时间】:2010-10-26 21:42:31 【问题描述】:

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

【问题讨论】:

要理解下面人们的回答,您可能需要问另一个问题:即“C++ 中的‘声明’和‘定义’有什么区别?” 我知道声明和定义的区别。 您可以包含任何您想要的内容,但是如果您将全局变量包含到多个编译单元中,链接阶段将会中断。这就是为什么约定不链接 .cpp 文件的原因。 【参考方案1】:

C++ 构建系统(编译器)没有区别,所以都是一种约定。

约定是.h 文件是声明,.cpp 文件是定义。

这就是为什么 .h 文件是 #included 的原因——我们包含了声明。

【讨论】:

C++ 构建系统确实有区别 - 例如,尝试在 .h 文件和 .cpp 文件上运行 g++,看看会发生什么。 我知道 .cpp 文件(大部分时间)用于定义已在 .h 文件中声明的函数/类/等,但您也可以在 .h 文件中定义变量。 @Neil Butterworth:是的,G++ 编译器理解约定,但您可以通过强制语言使其编译。 这就像说“Windows 不知道 .png.doc 之间的区别”。在某种程度上,它们都只是文件,Windows 不知道它们之间的区别。但是 Windows 被配置为以不同的方式对待它们。许多 C++ 构建系统已配置以了解差异。例如,默认情况下,Visual Studio 将.cpp 文件放在其vcxproj 文件中的<ClCompile /> 标记中,但同一项目中包含的头文件位于<ClInclude /> 标记中。 XCode 不会在其“构建阶段”选项卡的“编译源”下列出 .h 文件,但会在其中列出 .c.cpp.m.mm 文件。【参考方案2】:

.cpp 文件是编译单元:它将被编译的真正的源代码文件(在 C++ 中)。

.h(头文件)文件是虚拟复制/粘贴到出现#include 预编译器指令的 .cpp 文件中的文件。在.cpp代码中插入headers代码后,.cpp的编译就可以开始了。

【讨论】:

为什么说是 .cpp 文件而不是 .cpp 文件? @Keand64:因为编译器在编译时一次只查看 一个 .cpp 文件。它读取一个 .cpp 文件,读取所有 #included .h 文件,编译整个文件,写入一个 .o(或 .obj)文件,然后继续执行下一个 .cpp 文件。 这是否意味着.cpp和.h必须同名? @fathergorry 不,没有命名源文件的规则(头文件与否),只有约定。【参考方案3】:

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

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

【讨论】:

我知道他没有问为什么,但这对我来说是最有帮助的答案。了解原因可以更轻松地将逻辑与细节联系起来【参考方案4】:

标题(.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。就像 -x c++ 一样),人们总是可以告诉一个好的编译器如何处理某个文件。

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

【讨论】:

【参考方案5】:

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

鉴于:

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

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

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

【讨论】:

【参考方案6】:

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

【讨论】:

所以我猜 .h 类似于 C# 接口【参考方案7】:

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

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

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

【讨论】:

大多数人实际上也将 .h 用于 C++。 @Zifre:是的,因此我说这些是推荐的命名约定,尽管许多人可能不遵循它们。【参考方案8】:

按照惯例,.h 文件会被其他文件包含在内,而不会直接由它们自己编译。 .cpp 文件——再次按照惯例——是编译过程的根源;它们直接或间接包括 .h 文件,但通常不包括 .cpp 文件。

【讨论】:

以上是关于.cpp 文件和 .h 文件有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

请问C++中啥是函数的定义性声明和函数的引用性声明,有啥区别

Visual Studio 中的头文件、源文件和资源文件都是啥?有啥区别??

stdlib.h和stdio.h有啥区别

C语言编译器icc与gcc编译出来的执行文件有啥区别?

求教 vc++编程高手 :compile 与build 有啥区别和联系

C++中 string 和cstring 头文件 有啥区别????