.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
文件是 #include
d 的原因——我们包含了声明。
【讨论】:
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 中的头文件、源文件和资源文件都是啥?有啥区别??