对函数声明和原型感到困惑

Confused about function declarations and prototypes

我有一个简单的问题,但它困扰着我。我的在线教科书说这是真的 --> "A function declaration enables calls to the function before the function definition." 我认为这是假的,因为如果函数仅在声明后才被调用,程序怎么知道它做了什么。我认为这会导致编译时错误。有人可以解释为什么这是真的吗?谢谢。

这意味着一旦你声明函数,编译器就会知道它的存在。

因此您可以编写 调用 该函数的代码,并且编译器不会报错。这可能就是为什么您的教科书说 允许在函数定义之前调用函数

当然,您必须在某处定义函数(编写函数体)才能使程序正确执行。

文中并不表示声明足以让它工作,它只是说明声明函数允许编写调用它的代码而无需定义到位。

某些语言的某些编译器在代码中首次引用函数时需要知道函数的签名。

如果没有原型,程序员将不得不在函数被引用之前编写函数的定义。这将导致两个函数无法相互调用。

原型为编译器提供函数的签名,稍后将在代码中或可能在不同的代码文件中编写(定义)该函数。

给出声明后,该函数就可以通过代码用于编译。稍后可以验证和编译函数的定义。

在运行时,函数的调用者(基于声明)链接到定义。

Java

中的示例

在Java中接口中的一个方法可以看作是声明:

public interface IHelloWorld {

    void sayHello();

}

还有一个class实现了接口中声明的方法,定义为:

public class HelloWorld implements IHelloWorld {

    @Override
    public void sayHello(String name) {
        System.out.println("Hello " + name);
    }

}

当另一个class使用接口中的方法时,它有足够的信息来完成编译。在运行时,它需要获取实现接口的具体 class 的实例。


同样适用于抽象class,其中包含方法声明:

public abstract class AbstractHelloWorld {

    public void sayHello(String name);

}

具体的 class 看起来像:

public class HelloWorld extends AbstractHelloWorld {

    @Override
    public void sayHello(String name) {
        System.out.println("Hello " + name);
    }

}

你的书描述了我们所说的前向声明。

A forward declaration is a declaration of an identifier (denoting an entity such as a type, a variable, a constant, or a function) for which the programmer has not yet given a complete definition.

来源wikipedia

如果你采用函数声明,这意味着你告诉编译器你的函数将是什么样子(函数签名),以便你可以在代码中调用它,但编译器还不知道这个函数实际上是什么

C 中的示例

hello.h - 函数定义

void helloWorld();

hello.m - 函数声明

void helloWorld() {
   printf("Hello World");
}

这就是为什么要调用其中的函数必须包含 .h 文件的原因。

Objective C

中的例子
// I promise you (the compiler) that a class called MyClass exists
@class MyClass;
@interface MyInterface : NSObject {
    MyClass *evenThoughItDoesNotExistYet;
}
@end

"Implicit"前向声明

其他一些语言,如 ruby,在内部进行这种前向声明。为此,他们多次扫描代码以列出所有函数,然后验证代码中调用的所有函数是否存在。