【问题标题】:Implementing small functions in a header file, including in two different files in the same project在头文件中实现小功能,包括在同一个项目的两个不同文件中
【发布时间】:2020-08-31 22:36:12
【问题描述】:

来自learncpp.com 的关于是否在头文件中实现函数的引用:

  1. 对于仅在一个文件中使用且通常不可重用的类,请直接在使用它们的单个 .cpp 文件中定义它们。
  2. 对于在多个文件中使用的类,或用于一般重用的类,请将它们定义在与类同名的 .h 文件中。
  3. 可以在类内部定义普通成员函数(普通构造函数或析构函数、访问函数等)。
  4. 重要的成员函数应在与类同名的 .cpp 文件中定义。

假设我遵循#3 的建议,并在my_class.h 文件中实现了一些小方法my_class::f,但我将更大的方法留在my_class.cpp 中实现。如果我在同一个项目的两个不同的.cpp 文件中包含my_class.h,那么链接器将看到my_class::f 的两个(相同的)定义。 (这不是由标头保护解决的。)我知道一些链接器足够聪明,可以容忍这种情况(尽管我听说它可能会花费额外的时间)。我的问题是:

您认为他们推荐#3 是因为在一个项目中两次包含相同的 .h 文件是不常见的,还是因为可以依赖链接器来忽略重复的定义,并且这样做不会浪费太多时间?

【问题讨论】:

  • 你需要使函数inline避免重定义。
  • 推荐对 C++ 头文件使用 .hpp.hxx。这将区分 C 语言头文件 .h 和 C++ 头文件。 C 编译器无法编译 C++ 头文件。

标签: c++ linker header-files one-definition-rule


【解决方案1】:

我知道有些链接器足够聪明,可以容忍这种情况

所有符合标准的链接器允许多个相同的内联函数定义。

可以依赖链接器来忽略重复的定义

是的。

这样做不会浪费太多时间吗?

我不认为链接器浪费的时间会很大。

但是,内联函数通常必须针对使用它们的每个翻译单元进行编译。如果它是一个特别复杂的函数,那么编译器(而不是链接器)最终可能会浪费大量时间。这也是本教程建议仅内联定义琐碎函数的部分原因。

遵循(暗示的)建议(not 内联定义非平凡函数)的另一个原因是非平凡函数会吸引更改,并且对头文件的修改会随着对包含以下文件的更改传播那些标题。非内联函数不需要重复编译,并且在更改时也不会导致其他翻译单元被编译,因此可以将重新编译时间减少到整个编译时间的一小部分。

【讨论】:

  • 教程建议在源文件中定义大部分代码,这很奇怪。标准库有超过一百万行模板化的仅标头代码。即使在 50 行代码中,编译器也可能会从可用的函数定义中受益,并且仍然部分内联它们。
  • @JanSchultke 当您编写模板时,您很少有机会在单独的翻译单元中定义功能。但是,对于非模板函数,非内联函数可能会因为将重新编译时间缩短到整个编译时间的一小部分而感到愤怒。
【解决方案2】:

在建议 #3 中写到

平凡的成员函数(平凡的构造函数或析构函数,访问 函数等...)可以在类中定义

类中定义的成员函数是内联函数。所以在几个编译单元中包含header是没有问题的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-18
    • 2013-01-17
    • 1970-01-01
    • 1970-01-01
    • 2014-02-19
    • 2015-12-19
    • 2013-09-05
    • 1970-01-01
    相关资源
    最近更新 更多