22

我想写一个库来使用,你只需要包含一个头文件。但是,如果您有多个源文件并在两者中都包含标头,则会出现多个定义错误,因为该库既在标头中声明又在标头中定义。我认为,在 Boost 中,我已经看到了只有标头的库。他们是怎么做到的?

4

4 回答 4

38

声明你的函数inline,并将它们放在一个命名空间中,这样你就不会发生冲突:

namespace fancy_schmancy
{
  inline void my_fn()
  {
    // magic happens
  }
};
于 2010-10-19T22:16:06.477 回答
6

Boost 主要是仅标题的主要原因是因为它非常面向模板。模板通常从单一定义规则中获得通过。事实上,要有效地使用模板,您必须使定义在使用该模板的任何翻译单元中可见。

绕过单一定义规则 (ODR) 的另一种方法是使用inline函数。实际上,从 ODR 获得免费通行证才是inline真正的作用——它可能内联函数这一事实实际上更像是一种可选的副作用。

最后一个选择(但可能不是那么好)是让你的函数静态化。如果链接器无法确定所有这些函数实例确实相同,这可能会导致代码膨胀。但我提到它是为了完整性。请注意,编译器通常会内联static函数,即使它们没有标记为inline.

于 2010-10-19T22:38:20.790 回答
2

Boost 大量使用仅标头库,因为与 STL 一样,它主要使用类和函数模板构建,它们几乎总是仅标头。

如果您不编写模板,我会避免在您的头文件中包含代码 - 这比它的价值更麻烦。使它成为一个普通的旧静态库。

于 2010-10-19T22:35:42.647 回答
1

有许多真正只有标头的 Boost 库,但它们往往非常简单(和/或只有模板)。更大的库通过一些技巧实现了相同的效果:它们具有“自动链接”(您将在此处看到该术语)。它们本质上在标头中有一堆预处理器指令,它们为您的平台找出适当的 lib 文件并使用 a#pragma指示链接器将其链接。因此您不必显式链接它,但它仍在被链接.

于 2010-10-19T22:35:46.443 回答