【问题标题】:Does the module standard for C++ solve the problem of hiding private data from callers?C++ 的模块标准是否解决了对调用者隐藏私有数据的问题?
【发布时间】:2019-08-01 14:57:30
【问题描述】:

在 C++ 中,模块被标准化以解决 #include 膨胀等问题。 C++ 中的编译器必须解析太多。

而且,由于 C++ 内联存储数据的效率很高,因此调用者也必须知道对象的内存布局。

即将发布的模块标准是否解决了这个问题?

例子:

class GLWin {
private:
  GLFWwindow* win;
  glm::mat4 projection;
  ...
};

包含指向内部实现的指针的对象可以通过空声明解耦,即:

类 GLFWwindow;

但是,如果为了性能,我们在窗口中包含 mat4 对象,那么我们需要知道大小,这目前意味着包含一个定义,引入一个由于级联包含而通常很大的头文件。模块中是否有任何机制可以隐藏细节并允许为对象保留正确的空间量,同时使其像指针一样不透明?

【问题讨论】:

    标签: c++ c++20 c++-modules


    【解决方案1】:

    模块无法实现这样的系统,即模块外部的代码不知道类型的私有成员是什么。这不适用于静态反射提议,它允许对类型的私有成员进行查询和迭代。

    模块的作用是:

    1. 当您获得这些递归“包含”时,它们实际上并没有这些内部结构暴露给外部代码。在您的示例中,假设glm::mat4 来自一个名为GLM 的模块。声明GLFWin 的模块将具有import GLM,因为它需要这些定义才能工作。然而,这是一个实现细节,所以你不会做export import GLM

      现在,其他人来导入您的模块。要执行该导入,编译器必须读取GLM 模块。但是因为你的模块没有导出GLM,所以导入你的模块的代码不能使用它。也就是说,他们自己不能使用glm::mat4 或其他任何东西,除非他们自己导入该模块。

      这似乎没有太大区别,因为 GLM 模块仍然是必需的,但它是一个重要的模块。用户不会仅仅因为他们正在使用的模块正在使用该模块而从模块中获取接口。

    2. 这些导入几乎没有那么痛苦。编译模块的结果应该是一个文件(通常称为 BMI,“二进制模块接口),这是编译器可以快速读取并转换为其内部数据结构的文件。此外,如果您在同一个中编译多个翻译单元编译器进程,然后它们可以共享加载的模块。毕竟,GLM 不会根据您从哪里导入它而改变,因此甚至没有理由重新加载模块;您只需使用内存中已有的内容。

      最后是重新编译。如果您正在使用头文件,并且您更改了 GLM 头文件,那么包含它们的每个文件都需要重新编译。模块仍然如此,但痛苦要小得多。

      假设您的 GLFWin-creating 模块和使用它的模块在某个时候都使用 std::vector。现在,假设您更改了 GLM,因此您必须重新编译这两个模块。在标头世界中,这个 also 意味着两个文件都必须重新编译 <vector> 标头,即使它没有更改并且根本不依赖于 GLM。这就是文本包含的工作原理。

      在模块化世界中,他们不必重新编译 vector 模块。它不以任何方式依赖GLM 模块,因此它可以只使用已经存在的vector 模块。对于不依赖于GLM任何 包含的模块也是如此。因此,尽管您仍然需要级联的重新编译,但重新编译本身应该会更快,因为不必重新编译每个翻译单元本身使用的所有内容。 5000 行文件像 5000 行文件一样重新编译,而不是 5000 +,无论它包含多少行。

    【讨论】:

      【解决方案2】:

      模块概念改变了我们对依赖项的看法。将不再有头文件,只有二进制模块接口 (BMI),它由编译器生成,包含有关对象大小、对象结构和依赖关系的所有信息。你的类的模块必须依赖于 GLFWindow 和 glm::mat 的模块,否则你不能编译它。因此,从某种意义上说,您仍然必须将内部数据公开给其他类,但是您的编译器不必爬取所有包含,而只需爬取 BMI 的导入,这是理解类/函数接口以及它是否发现所必需的多次相同的 BMI 作为依赖,它只会解析一次。

      这也意味着,您将不再将定义和声明分开在单独的文件中,因为它没有任何意义。你最终会得到一个看起来更像 Java .class 文件的东西。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-02-10
        • 1970-01-01
        • 2010-09-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-05-15
        • 1970-01-01
        相关资源
        最近更新 更多