关于c++头文件的简单问题

Simple question about header files in C++

本文关键字:简单 问题 文件 c++ 关于      更新时间:2023-10-16

假设我有3个文件:add.h, add.cpp和main.cpp。这是c++培训网站上的一个常见示例,其中add.h包含一个名为"add"的函数的原型。add. cpp包含原型的声明,main.cpp包含add.h,然后调用add()函数将两个数字(x和y)相加。

我的问题是:无论我命名add.cpp,我的程序工作得很好。Elephant.cpp和doctor whorrules .cpp一样有效。编译器是否搜索所有本地.cpp文件以在add.h中找到给定的原型?我没有在任何地方声明包含它的.cpp文件的名称。我只是不明白这是怎么回事。

谢谢!

我想你把JavaC++混在一起了。在Java(像Eclipse这样的编辑器)中有一个一般的限制,您的class名称应该与文件名相同。例如

// Add.java
class Add
{
}

在c++中没有这样的限制。文件名可以是任何有意义的名称。你唯一要注意的是你的实现文件是.cpp/.cxx/.C等扩展(我不知道现代编译器是否支持这以外的)。

甚至你的头文件也可以是任意的扩展名当然,除了.cpp和所有;更常规的头文件扩展名是.h, .hpp

这些名称是惯例。你可以给它取任何你喜欢的名字,包括"每周时事通讯"。你不必使用"add.cpp"

也就是说,除非你有理由不这样做,否则遵循惯例是明智的,有些工具会使用扩展名来推断所使用的语言。

作为一个例子,当人们把"foo.cpp"文件当作头文件使用时,非常令人困惑!然而,这在c++中是允许的。然而,这是违反惯例的,而且编程已经足够困难了。

不同的可能性;

1)您实际上并没有重命名文件,您只是将文件保存在一个新名称下—旧的add.cpp仍然存在并且仍然有效。

2)有一个旧的add.obj,这是得到链接的

3)文件作为一个项目被打开,visual studio发现打开的文件实际上都是你想要编译的文件,exe

是的,编译器搜索所有的文件。更准确地说,它做了一次传递("编译"),将你的代码简化为机器指令,并向每个文件添加它全局定义的符号列表(函数名和变量名),然后第二次传递("链接",技术上根本不是编译器的一部分),将这些名称相互匹配。

.h文件中的原型的意义仅仅是为了使编译器在编译main.cpp时,可以使用在add.cpp(或者你叫它什么)中实际定义的确切类型和名称。这使得在不实际看到实现文件的情况下执行编译部分成为可能。

但是,

模板打破了这种"单独编译"模型,因为编译器在编译期间需要看到模板的整个定义,因为它必须根据模板的调用方式生成特定于类的代码。通常,模板放在.h文件中,并包含在任何地方。

参见上面的文件名答案。链接器收集目标文件,匹配代码等,并构建可执行文件

假设我们有add.h add.cpp和main.cpp.

在main.cpp和add.cpp中都需要add的原型。Main.cpp需要它是因为它想使用add类,而add.cpp需要它是因为它想实现它,因此需要它的原型。这是通过包含头文件来完成的。在add.cpp和main.cpp中都包含"add.h"

现在编译器开始工作,创建两个目标文件,即main。0加0。所以仍然主要只知道添加,内部机制(实现)仍然不存在。之后,链接器结合main。O和add. O合并到一个可执行文件中,该文件具有从main中运行add的所有附加功能。

编译后,每个目标文件都知道其名称。在链接之后,他们实际上知道如何通过名称(他(实现)所在的位置)调用它们。

在编译器之前,还有一个步骤叫做预处理。在这个步骤中要做的一件事是复制#include.

后面的文件的内容。

无论如何调用add.h都无关紧要,但必须在main.cpp和add.cpp中包含正确的文件。无论您如何调用add.cpp或main.cpp都无关紧要,只有您的编译器必须被告知如何调用它们。例如,在visual studio中,这是自动完成的,通过在项目文件中重命名它们。如果使用gcc,你必须自己指示编译器和链接器。在这种特定情况下,您可以执行以下操作。

编译add.cpp为add.o:

gcc -c add.cpp

编译main.cpp为main.cpp:

gcc -c main.cpp

链接add.o和main。

gcc -o myniceprogram add.o main.o