为什么C++需要通过标头或语句进行前向声明,而 Java 不需要?

why does a C++ need a forward declaration either through a header or a statement and Java doesn't need?

本文关键字:声明 不需要 Java 语句 C++ 为什么      更新时间:2023-10-16

如果你不转发声明你的函数,Java不会抱怨,而C++会抱怨。我知道C++涉及预处理,但我想了解更多。

对象文件

Java 编译器依赖于编译到它们生成的字节码 (.class) 文件中且您的代码使用的额外信息,而C++编译器不会将此类信息存储在它们生成的编译对象代码 (.obj) 文件中。

作为一种较旧的语言,C++依赖于程序编译和链接的"C模型"。这意味着对象文件主要包含代码和数据,只有足够的元数据即可将目标文件链接在一起(在运行时静态或动态)。因此,编译器依赖于解析源代码时包含的头文件来了解代码引用的外部类类型、函数和变量。

这也意味着C++代码的客户端需要代码的目标文件(.obj、.lib 或 .dll)和头文件才能自行使用它。

Java 是一种更现代的语言,它将大量符号元数据存储到它生成的对象 (.class) 文件中,这允许编译器在以后的编译中提取代码引用的外部类类型、方法和变量。

这也意味着 Java 代码的客户端只需要代码的目标文件(.class 或 .jar)即可使用它。

前瞻声明

Java编译器对源代码进行多次传递,这意味着你只需要在代码中的一个位置声明/定义一个变量或方法;前向声明不是必需的,因为编译器更努力地确定类型信息。

相比之下,C++被定义为

可以将其实现为单通道编译器,这意味着编译器需要在源代码中使用时了解有关类、变量或方法的所有相关类型信息。这意味着您必须在代码中的实际对象定义之前提供该类型声明信息。这就是使用头文件的原因。

Java使用.class文件格式。编译器收集有关类的信息并将其放入.class文件中。在结果中,可以在不涉及源文件的情况下完成链接。请注意,在 Java 中,每个文件都有一个公共类需求,因此为每个源文件生成一个.java .class

在C++代码通常被编译为object文件,这些文件不知道类或结构等高级概念。因此,必须在头文件中提供信息,以便编译器可以在进入链接阶段之前执行检查(甚至知道如何生成一些代码)。

我一直在寻找前向声明背后的基本原理,但是 K&R 的 ANSI C(它可能是从 C 继承的"功能")只是声明每个变量必须在使用前声明,并且 ANSI C 对与定义一致的函数进行了前向声明(它们之前不需要兼容)。

因为 c++ 没有导出模块定义的概念。如果要公开函数或类,以便其他.cpp(模块)可以访问它,则必须在.h文件中转发声明它们。为什么不在 .h 中编写整个函数(定义)和类,而不是前向声明它们并写在 .cpp 文件中? 因为当你 #include 它几乎包含了整个.h文件的内容.cpp所以如果你把它包含在你拥有的所有.cpp文件中,它将在每个.cpp中重复编译。这可能效率极低。因此,您只需要 .h 中的前向声明和.cpp中的所有定义。