在这一环节,有人提到下列事项:

add.cpp:

int add(int x, int y)
{
    return x + y;
}

main.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”是什么。如前所述,为您想要使用的位于另一个文件中的每个函数编写前向声明很快就会变得乏味。

你能进一步解释一下“前向申报”吗?如果我们在主函数中使用它会有什么问题?


当前回答

一个简短的补充:通常你把这些转发引用放在一个头文件中,属于实现函数/变量等的。c(pp)文件。在你的例子中,它看起来像这样: add.h:

extern int add(int a, int b);

关键字extern表示函数实际上是在外部文件中声明的(也可以是库等)。 你的main.c应该是这样的:

#include 
#include "add.h"

int main()
{
.
.
.

其他回答

编译器查找在当前翻译单元中使用的每个符号是否先前声明在当前单元中。这只是一个样式问题,在源文件的开头提供所有方法签名,而稍后提供定义。它的重要用途是将一个类的指针用作另一个类的成员变量。

//foo.h
class bar;    // This is useful
class foo
{
    bar* obj; // Pointer or even a reference.
};

// foo.cpp
#include "bar.h"
#include "foo.h"

因此,尽可能在类中使用前向声明。如果您的程序只有函数(带有ho头文件),那么在开始时提供原型只是一个风格问题。如果头文件出现在一个只有函数头的普通程序中,那么无论如何都会出现这种情况。

因为c++是由上而下解析的,所以编译器需要在它们被使用之前知道它们。所以,当你引用:

int add( int x, int y )

在main函数中,编译器需要知道它的存在。为了证明这一点,尝试将它移动到主函数的下面,你会得到一个编译器错误。

所以“远期申报”就是罐头上写的。它在使用之前就声明了一些东西。

通常你会在头文件中包含前向声明,然后以包含iostream的相同方式包含该头文件。

当编译器看到add(3,4)时,它需要知道这意味着什么。通过forward声明,你基本上告诉编译器add是一个接受两个int型并返回一个int型的函数。这对编译器来说是很重要的信息,因为它需要将正确表示形式的4和5放到堆栈中,并且需要知道add返回的东西是什么类型。

那时,编译器并不担心add的实际实现,即它在哪里(或者是否有一个)以及它是否编译。稍后,在调用链接器时编译源文件之后,就会看到它。

一个简短的补充:通常你把这些转发引用放在一个头文件中,属于实现函数/变量等的。c(pp)文件。在你的例子中,它看起来像这样: add.h:

extern int add(int a, int b);

关键字extern表示函数实际上是在外部文件中声明的(也可以是库等)。 你的main.c应该是这样的:

#include 
#include "add.h"

int main()
{
.
.
.

int add(int x, int y); // forward declaration using function prototype

你能解释一下“前向声明”吗? 更多的进一步的吗?如果有什么问题 我们在main()函数中使用它?

它与#include"add.h"相同。如果你知道,预处理器会展开你在#include中提到的文件,在你写#include指令的。cpp文件中。这意味着,如果你写#include"add.h",你会得到同样的东西,就好像你在做"前向声明"。

我假设add.h有这一行:

int add(int x, int y);