在 此 链接中,提到了以下内容:
添加.cpp:
int add(int x, int y)
{
return x + y;
}
主.cpp:
#include <iostream>
int add(int x, int y); // forward declaration using function prototype
int main()
{
using namespace std;
cout << "The sum of 3 and 4 is " << add(3, 4) << endl;
return 0;
}
我们使用了前向声明,以便编译器在编译
main.cpp
时知道“add
”是什么。如前所述,为要使用的每个位于另一个文件中的函数编写前向声明会很快变得乏味。
你能进一步解释一下“ 前向声明”吗?如果我们在 main
函数中使用它会出现什么问题?
原文由 Simplicity 发布,翻译遵循 CC BY-SA 4.0 许可协议
为什么在 C++ 中需要前向声明
编译器希望确保您没有犯拼写错误或将错误数量的参数传递给函数。因此,它坚持在使用它之前首先看到“add”(或任何其他类型、类或函数)的声明。
这实际上只是允许编译器更好地验证代码并允许它整理松散的末端,以便它可以生成一个看起来整洁的目标文件。如果您不必转发声明内容,编译器将生成一个目标文件,该文件必须包含有关函数
add
可能是什么的所有可能猜测的信息。当add
函数可能存在于链接器加入的不同目标文件中时,链接器必须包含非常聪明的逻辑来尝试add
您实际打算调用的 —与使用 add 产生dll
或exe
的那个。链接器可能会出错add
。假设您想使用int add(int a, float b)
,但不小心忘记写它,但链接器发现了一个已经存在的int add(int a, int b)
并认为这是正确的并使用了它。您的代码会编译,但不会按照您的预期进行。因此,为了保持明确并避免猜测等,编译器坚持要求您在使用之前声明所有内容。
声明与定义的区别
顺便说一句,了解声明和定义之间的区别很重要。声明只提供了足够的代码来显示某些东西的样子,因此对于函数,这是返回类型、调用约定、方法名称、参数及其类型。但是,不需要该方法的代码。对于定义,您需要声明,然后还需要函数的代码。
前向声明如何显着减少构建时间
您可以将函数声明添加到当前的
.cpp
或.h
文件中,方法是#includ’ing 已经包含函数声明的标头。但是,这可能会减慢您的编译速度,特别是如果您将程序的#include
标头放入.h
而不是.cpp
.h
所有内容---
你写的最后会#include’ing你写#includes的所有标题。突然间,编译器有#included 页面和需要编译的代码页面,即使您只想使用一两个函数也是如此。为避免这种情况,您可以使用前向声明并在文件顶部自己键入函数的声明。如果您只使用几个函数,与总是#include 标头相比,这确实可以使您的编译更快。对于非常大的项目,差异可能是一个小时或更长时间的编译时间缩短到几分钟。中断两个定义都相互使用的循环引用
此外,前向声明可以帮助您打破循环。这是两个函数都试图相互使用的地方。当这种情况发生时(这是一件非常有效的事情),您可能会
#include
一个头文件,但该头文件会尝试#include
您当前正在编写的头文件。 .. 然后 #includes 另一个标题,其中 #includes 您正在编写的标题。您陷入了先有鸡还是先有蛋的困境,每个头文件都试图重新#include 另一个。要解决此问题,您可以在其中一个文件中前向声明您需要的部分,并将#include 保留在该文件之外。例如:
文件车.h
文件轮.h
Hmm… the declaration of
Car
is required here asWheel
has a pointer to aCar
, butCar.h
can’t be包括在此处,因为它会导致编译器错误。 IfCar.h
was included, that would then try to includeWheel.h
which would includeCar.h
which would includeWheel.h
and this would go on forever ,因此编译器会引发错误。解决方案是转发声明Car
代替:If class
Wheel
had methods which need to call methods ofCar
, those methods could be defined inWheel.cpp
andWheel.cpp
is now able to包括Car.h
而不会导致循环。