请注意,实现文件没有为&尊龙凯时官方网站nbsp;person 模块的导入声明。module person 声明隐含地包括了 import person 声明。同样值得注意的是,尽管在方法实现中使用了 std::string,实现文件也没有对 string 的任何导入声明。由于隐含的 import person,以及因为此实现文件是同一个 person 模块的一部分,它隐含地继承了模块接口文件中的 string 导入声明。 相比之下,向 test.cpp 文件添加 import person 声明并不会隐含地继承 string 导入声明,因为 test.cpp 不是 person 模块的一部分。关于这方面有更多内容,在即将到来的 可见性与可达性 一节中进行讨论。 注意:模块接口和模块实现文件中的所有导入声明都必须位于文件顶部,在命名模块声明之后,但在任何其他声明之前。与模块接口文件类似,如果在模块实现文件中需要任何传统头文件的 #include 指令,你应该将它们放在全局模块片段中,其语法与模块接口文件相同。 警告:模块实现文件不能导出任何内容;只有模块接口文件可以。 当使用头文件(.h)而非模块时,强烈建议只在头文件中放置声明,并将所有实现移至源文件(.cpp)。这样做的一个原因是为了提高编译时间。如果将实现放在头文件中,任何更改,即使只是修改一个注释,也需要重新编译包含该头文件的所有其他源文件。对于某些头文件,这可能会导致整个代码库的全面重新编译。通过将实现放在源文件中,不触及头文件的情况下对这些实现进行修改,意味着只需要重新编译那个单独的源文件。 模块的工作方式不同。模块接口仅包括类定义、函数原型等,但不包括任何函数或方法的实现,即使这些实现直接位于模块接口文件中。因此,更改模块接口文件内的函数或方法实现,只要不触及接口部分(例如,函数头 = 函数名、参数列表和返回类型),就不需要重新编译使用该模块的用户。 有两个例外:使用 inline 关键字标记的函数/方法,以及模板定义。对于这两者,编译器需要在编译使用它们的客户端代码时了解它们的完整实现。因此,对 inline 函数/方法或模板定义的任何更改都可能触发客户端代码的重新编译。 注意:当头文件中的类定义包含方法实现时,这些方法即使没有标记 inline 关键字,也会被隐式地视为内联。但这对于模块接口文件中类定义中的方法实现不成立。如果这些需要被内联,它们需要被显式地标记为此。 尽管从技术上讲,不再需要将接口与实现分离,但在某些情况下,我仍然建议这样做。主要目标应该是拥有清晰易读的接口。只要函数的实现不会遮蔽接口,使用户难以快速理解公共接口提供了什么,就可以保留在接口中。例如,如果一个模块有一个较大的公共接口,最好不要用实现来遮蔽该接口,这样用户可以更好地了解所提供的内容。然而,小的 getter 和 setter 函数可以保留在接口中,因为它们对接口的可读性影响不大。 从实现中分离接口可以通过几种方式完成。一种选择是将模块分为接口和实现文件,如前一节所讨论的。另一种选择是在单个模块接口文件内分离接口和实现。例如,以下是在单个模块接口文件(person.cppm)中定义的 Person 类,但将实现与接口分离: |
部门热线
前 台:13588889999
业务部:13588889999
客服部:13588889999
技术部:13566667777
人事部:13566667777