我有点困惑。前向声明和前向引用有什么区别?在我看来,前向声明是当你声明一个尚未实现的函数时,但这不正确吗?您是否必须查看特定情况以声明案例“前向引用”或“前向声明”?
3 回答
前向声明是在实现和使用方法或变量之前的声明。前向声明的目的是节省编译时间。
变量的前向声明会导致存储空间被留出,因此您可以稍后设置该变量的值。
函数的前向声明也称为“函数原型”,是一种声明语句,它告诉编译器函数的返回类型是什么,函数的名称是什么,以及它的参数类型。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 的超集,因此必须使用相同的机制。
到 1995 年 Java 出现时,普通计算机已经拥有足够的内存来保存一个符号表,即使对于一个复杂的项目,也不再是一个沉重的负担。而且 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);
}
请注意,“前向引用”有时用作“前向声明”的同义词,但并不经常使用。
来自维基百科:
前向声明
尚未定义的变量或函数的声明。稍后可以看到它们的定义。
前向参考
与前向声明类似,但在变量或函数首先出现的地方,定义也已到位。
前向声明用于允许对一种语言(C、Pascal)进行单遍编译。
如果在没有前向声明的情况下允许前向引用(Java、C#),则需要两遍编译器。