仅使用标头实现的重复符号

Duplicate symbols with header only implementation

本文关键字:符号 实现      更新时间:2023-10-16

我有一个在头文件中声明和实现的C++类。我之所以选择这个,是因为由于_GLIBCXX_DEBUG和预编译库,人们无法轻松地在调试和发布版本之间移动。例如,如果我定义_GLIBCXX_DEBUG,Boost 将由于源文件中的 ABI 更改而崩溃。

仅标头实现产生了重复符号的问题。例如,在下面的类中,operator== 和非成员swap将生成乘法定义的符号。

// Foo.hpp
namespace Bar
{
  template
  class Foo
  {
    ...
  };
  bool operator==(const Foo& a, const Foo& b) {
    ..
  }
}
namespace std
{
  template <>
  void swap(Bar::Foo& a, Bar::Foo& b)
  {
    a.swap(b);
  }
}

当声明和实现被拆分时,文件(Foo.hpp 和 Foo.cpp)编译并链接 OK。

让它正确编译和链接的诀窍是什么?

inline bool operator==(const Foo& a, const Foo& b) {
    ..
  }

成员函数是隐式内联的,前提是它们在其类中定义。同样的事情对他们来说也是如此:如果他们可以毫不费力地放入标题中,你确实可以这样做。

由于函数的代码

被放入标头中并且可见,因此编译器能够对它们进行内联调用,也就是说,将函数的代码直接放在调用站点(与其说是因为您将内联放在它之前,不如说是因为编译器决定这样做。仅内联是编译器对此的提示)。这可以提高性能,因为编译器现在可以查看参数与函数本地变量匹配的位置,以及参数不会相互别名的位置 - 最后但并非最不重要的一点是,不再需要函数帧分配。