Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 像C和Java这样的语言如何避免C/C++-像独立编译吗?_C#_Java_Compiler Construction_Programming Languages - Fatal编程技术网

C# 像C和Java这样的语言如何避免C/C++-像独立编译吗?

C# 像C和Java这样的语言如何避免C/C++-像独立编译吗?,c#,java,compiler-construction,programming-languages,C#,Java,Compiler Construction,Programming Languages,在我的编程语言课上,我正在写一篇关于语言设计史上一些重要人物的论文的研究论文。一辆车HOLL让我感到奇怪,因为它在C甚至流行之前反对C和后来的C++中使用的独立编译技术。 既然这主要是为了加快编译时间而进行的优化,那么Java和C#是什么让它们能够避免依赖独立编译的呢?这是一种编译技术,还是语言中有促进这一点的元素?还有其他编译语言在使用这些技术之前吗?IMO,这里最大的因素之一是java和.NET都使用中间语言;这意味着编译单元(jar/assembly)包含大量关于类型、方法等的表达元数据;

在我的编程语言课上,我正在写一篇关于语言设计史上一些重要人物的论文的研究论文。一辆车HOLL让我感到奇怪,因为它在C甚至流行之前反对C和后来的C++中使用的独立编译技术。
既然这主要是为了加快编译时间而进行的优化,那么Java和C#是什么让它们能够避免依赖独立编译的呢?这是一种编译技术,还是语言中有促进这一点的元素?还有其他编译语言在使用这些技术之前吗?

IMO,这里最大的因素之一是java和.NET都使用中间语言;这意味着编译单元(jar/assembly)包含大量关于类型、方法等的表达元数据;这意味着它已经被方便地布置好以供参考检查。运行时仍然会进行检查,以防拉得太快-p

虽然TLB通常是一个独立的实体,但它与支撑COM的MIDL距离不远


如果我误解了你的意思,请告诉我…

它需要一些语言支持(否则,C/C++编译器也会这样做)

特别是,它要求编译器生成自包含的模块,这些模块公开元数据,其他模块可以引用元数据来调用这些元数据

.NET程序集是一个简单的示例。项目中的所有文件一起编译,生成一个dll。NET可以查询此dll以确定其包含的类型,以便其他程序集可以调用其中定义的函数

为了利用这一点,在语言中引用其他模块必须是合法的

在C++中,什么定义模块的边界?该语言指定编译器只考虑其当前编译单元(.cpp文件+包含的标头)中的数据。没有任何机制可以指定“我想在模块栏中调用函数Foo,即使我在编译时没有原型或任何东西”。在文件之间共享类型信息的唯一机制是使用#includes

<> P>有一个建议,将模块系统添加到C++中,但它不会在C++ 0x中。最后一次看到,计划是在0x结束后考虑Tr1。< /P>
(值得一提的是,C/C++中的#include系统最初被使用是因为它可以加快编译速度。早在70年代,它允许编译器在简单的线性扫描中处理代码。它不必构建语法树或其他类似的“高级”功能。今天,表格已经发生了变化,它已经成为可用性和编译速度方面的一个巨大瓶颈。)

由C/C++生成的目标文件只能由链接器读取,而不能由编译器读取。

至于其他语言:IIRC Turbo Pascal有“单元”,可以在没有任何源代码的情况下使用。我认为重点是创建元数据以及编译后的代码,然后编译器可以使用这些代码来确定模块的接口(即函数签名、类布局等)

C/C++的一个问题是预处理器,它可以完全改变包含/导入模块的含义/语法等。C/C++阻止用某种导入替换包含。对于类似Java的模块系统来说,这将是非常困难的(如果不是不可能的话)。

简短回答:Java和C#不要避免单独编译;他们充分利用了它

它们的不同之处在于,在编写可重用库时,不需要程序员编写一对单独的头文件/实现文件。用户编写一次类的定义,编译器从该定义中提取相当于“头”的信息,并将其作为“类型元数据”包含在输出文件中。因此,输出文件(Java中充满
.class
文件的
.jar
文件,或基于.NET语言的
.dll
程序集)是二进制文件和头文件在单个包中的组合

然后,当编译另一个类并且它依赖于第一个类时,它可以查看元数据,而不必查找单独的包含文件

碰巧他们的目标是虚拟机,而不是特定的芯片架构,但这是一个单独的问题;他们可以将x86机器代码作为二进制文件放入,并且在同一个文件中仍然具有类似头的元数据(这实际上是.NET中的一个选项,尽管很少使用)

在C++编译器中,使用“预编译头”来加快编译速度是很常见的。.NET
.dll
.class
文件中的元数据非常类似于预编译的头文件-已被解析和索引,可供快速查找


结果是,在这些现代语言中,有一种方式进行模块化,它具有一个完美的组织和手工优化的C++模块化构建系统的特性——非常漂亮,讲。

< P>可以考虑java类文件类似于C/C++中的预编译头文件。本质上,.class文件是C/C++链接器需要的中间形式,以及头中包含的所有信息(Java没有单独的头)

在另一篇帖子中发表您的评论:

“我的意思基本上是 每个源文件都是它自己的 个人编译单元。此 在中国似乎不是这样 C#或Java。“

在Java中(我不能代表C#,但我假设它是相同的),每个源文件都是它自己的编译单元。我不知道你为什么会认为它不是。。。也许我们对编译单元有不同的定义?

我相信你对我的理解是正确的。我基本上是指C/C++中的想法,即每个源文件都是其各自的co