模块是否为C++;解决了对呼叫者隐藏私有数据的问题? 在C++中,模块被标准化以解决包括其他事物的膨胀问题。C++中的编译器必须分析得太多。 此外,因为C++在数据中高效地存储数据,甚至调用方也必须知道对象的内存布局。

模块是否为C++;解决了对呼叫者隐藏私有数据的问题? 在C++中,模块被标准化以解决包括其他事物的膨胀问题。C++中的编译器必须分析得太多。 此外,因为C++在数据中高效地存储数据,甚至调用方也必须知道对象的内存布局。,c++,c++20,c++-modules,C++,C++20,C++ Modules,即将发布的模块标准是否解决了这个问题 例如: class GLWin { private: GLFWwindow* win; glm::mat4 projection; ... }; 包含指向内部实现的指针的对象可以通过空声明进行解耦,即: 类窗口 但是,为了提高性能,如果我们在窗口中包含mat4对象,那么我们需要知道其大小,这目前意味着包含一个定义,引入一个头文件,由于级联包含,头文件通常非常大。模块中是否有任何机制可以隐藏细节并允许为对象保留正确的空间量,同时使其像指针一样不透

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

例如:

class GLWin {
private:
  GLFWwindow* win;
  glm::mat4 projection;
  ...
};
包含指向内部实现的指针的对象可以通过空声明进行解耦,即:

类窗口


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

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


这也意味着,您将不再在单独的文件中分离定义和声明,因为这没有任何意义。您将得到一个更像Java.class文件的文件。

模块无法实现系统,因此模块外部的代码不知道类型的私有成员是什么。这对静态反射建议不起作用,因为静态反射建议允许对类型的私有成员进行查询和迭代

模块所做的是使其能够:

  • 当您得到这些类型的递归“包含”时,它们实际上不会将这些内部代码公开给外部代码。在您的示例中,假设
    glm::mat4
    来自名为
    glm
    的模块。声明
    GLFWin
    的模块将具有
    import GLM
    ,因为它需要这些定义才能工作。但是,这是一个实现细节,因此您不会执行
    export-import-GLM

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

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

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

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

    让我们假设您的
    GLFWin
    -创建模块和使用它的模块在某个点上都使用
    std::vector
    。现在,假设您更改了GLM,那么您必须重新编译这两个模块。在标头世界中,这也意味着这两个文件都必须重新编译
    标头,即使它没有更改并且没有更改esn根本不依赖GLM。文本包含就是这样工作的

    在模块化的世界中,他们不必重新编译
    向量
    模块。它不以任何方式依赖于
    GLM
    模块,因此它可以只使用已经存在的
    向量
    模块。对于任何不依赖于
    GLM
    的包含模块来说,这是正确的。因此,尽管您仍然需要级联的重新编译,但由于不必重新编译每个翻译单元本身使用的所有内容,他自己重新编译的速度应该要快得多。一个5000行的文件就像一个5000行的文件一样重新编译,而不是5000+行,不管它包含多少行