C++20 中两种类型的模块文件(接口和实现)有何意义?

ard*_*bro 4 c++ c++20

当我想导出我编写的内容时,export void foo();我可以在同一个模块文件中实现它,也可以在单独的模块文件中执行它。但是,无论如何,我可以拥有任意数量的后一种类型,因此正式区分这些文件( export module mymodulevs )有什么意义。仅在我想要公开的内容之前module mymodule放置关键字而不需要费心处理特殊的接口文件还不够吗?export

Dav*_*ing 8

模块实现单元可以在其 module\xe2\x80\x99s 接口中使用具有模块链接(既不是export也不是static)的东西。如果所有模块单元都是接口单元和实现单元,则需要某种机制来处理这种访问的循环性

\n

其实现方式是将模块链接实体包含在已编译的模块接口文件中:立即了解翻译单元是否需要这种处理对于实现很有帮助。(这类似于需要知道文件属于哪个模块才能正确地修改其符号名称。)

\n

此外,要求预先声明模块接口的所有部分(在主接口中或在其招募的接口分区中)可以避免需要\xe2\x80\x9clink\xe2\x80\x9d多个独立模块单元的接口结果转化为一份 CMI 供进口商消费。事实上,除了通过链接不同的符号定义之外,模块实现单元不会影响导入器,这也有利于构建系统:当模块实现单元而不是接口单元发生变化时,导入器不需要重新编译

\n


Nic*_*las 5

在某些时候,构建系统会看到某个文件显示import MyModule;. 当它看到这一点时,构建系统需要去寻找MyModule.

如果MyModule尚未构建,构建系统需要构建它。为此,它必须(除其他外)扫描项目中的所有已知源文件,以查看哪些文件用于构建MyModule. 但最重要的是,它需要弄清楚它具体需要构建哪个文件才能import MyModule立即工作。

如果系统只需要查找要构建的单个文件,则该过程效果最佳且最快(这样,系统可以使用快速扫描仪预处理所有内容以查找所有这些文件)。因此,模块系统规定:对于任何特定模块,都有一个主模块接口,它定义了模块导出的所有内容。构建该模块可能会引发其他模块的编译,但我们知道哪个文件必须完成构建才能import MyModule工作。

现在将模块可以导出的所有内容都保存到一个文件中并不是最好的主意。因此,在许多情况下,您将有多个导出内容的文件,并将export import它们放在主要的主界面文件中MyModule。但由于模块名称是全局的,我们不希望数十个微小的模块名称弄乱命名空间。

输入模块分区:这些是模块接口文件,其模块名称在特定模块内“命名空间”。模块接口文件可以包含其他分区,但仅限于同一模块内的分区。显然,分区包含图必须是非循环的。

但这给我们留下了一个小问题。假设您有一个分区,它定义了一个导出到主模块接口的类。但您不想将这些成员函数的实现放在该分区文件中。那么...它去哪里了?

我的意思是,您可以将其放在另一个不会被任何人导入的分区中。但如果该分区没有被导入...为什么还要给它一个分区名称呢?最好能立即告知不能包含此“分区” 。

输入模块实施单位。它们是特定模块的一部分,因此它们可以导入该模块的分区。但它们本身不能被任何人进口。

这就是他们的目的。

但请注意,构建系统知道它不需要构建模块实现单元来完整构建模块。它只需要构建主模块接口文件及其包含的任何分区(直接或间接)。如果您将实现放入实现单元中,这可以使模块重建尽可能快。

最后,模块实现单元(和接口单元)可以访问它们从分区导入但该分区不导出的任何名称。这些模块本地名称只能在模块内访问。