答案 0 :(得分:28)
前向声明是在实现和使用它之前声明方法或变量。前向声明的目的是节省编译时间。
变量的前向声明会导致存储空间被搁置,因此您可以稍后设置该变量的值。
函数的前向声明也称为“函数原型”,它是一个声明语句,它告诉编译器函数的返回类型是什么,函数的名称是什么,以及它的参数类型。 C / C ++和Pascal等语言的编译器在查找表中声明符号(包括函数),并在代码中引用它们时引用它们。这些编译器按顺序读取您的代码,即从上到下,因此如果您不转发声明,编译器会发现它无法在查找表中引用的符号,并且会引发一个它不知道的错误如何回应这个功能。
前向声明是对编译器的一个暗示,您已在其他地方定义(填写了实现)该函数。
例如:
int first(int x); // forward declaration of first
...
int first(int x) {
if (x == 0) return 1;
else return 2;
}
但是,你问,为什么我们不让编译器对每个源文件进行两次传递:第一个用于索引内部的所有符号,第二个用于解析引用并查找它们?丹故事说:
当C于1972年创建时,计算资源更加稀缺 并且以高昂的价格 - 存储复杂物所需的内存 程序的整个符号表一下子就没有了 大多数系统。固定存储也很昂贵,而且非常慢 虚拟内存或存储符号表部分的想法 磁盘根本就不允许合理的编译 时间框架...当您处理寻求时间的磁带时 以秒为单位测量,读取吞吐量以字节为单位进行测量 第二个(不是千字节或兆字节),这非常有意义。
C ++,虽然在大约17年后创建,但被定义为超集 C,因此必须使用相同的机制。
当Java在1995年推出时,普通计算机已经足够了 即使对于复杂的项目,持有符号表的内存也是如此 不再是一个沉重的负担。并且Java不是设计的 向后兼容C,所以它不需要采用传统 机制。 C#同样没有受到阻碍。
因此,他们的设计师选择转移负担 区分符号声明退出程序员和 再把它放在电脑上,因为它的成本与之成比例 汇编的总工作量很小。
在Java和C#中,标识符自动从源文件中识别,并直接从动态库符号中读取。在这些语言中,出于同样的原因不需要头文件。
前向引用正好相反。它指的是在声明之前使用实体。例如:
int first(int x) {
if (x == 0) return 1;
return second(x-1); // forward reference to second
}
int second(int x) {
if (x == 0) return 0;
return first(x-1);
}
请注意,“前向引用”有时会用作“前向声明”的同义词,但不常用。
答案 1 :(得分:5)
来自Wikipedia:
前瞻性声明
声明尚未定义的变量或函数。他们的定义可以在以后看到。
转发参考
与Forward Declaration类似,但首先出现变量或函数,定义也已到位。
答案 2 :(得分:3)
前向声明用于允许单一语言编译(C,Pascal)。
如果在没有前向声明(Java,C#)的情况下允许前向引用,则需要双向编译器。