【问题标题】:Duplicate symbols with header only implementation [duplicate]仅具有标头实现的重复符号[重复]
【发布时间】:2012-11-07 00:01:50
【问题描述】:

我有一个在头文件中声明和实现的 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。

有什么诀窍可以让它正确编译和链接?

【问题讨论】:

  • 我的猜测是头文件必须是内联函数

标签: c++ compiler-construction build symbols


【解决方案1】:
inline bool operator==(const Foo& a, const Foo& b) {
    ..
  }

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

因为函数的代码放在头部并且可见,所以编译器能够内联调用它们,即直接将函数的代码放在调用位置(不是因为你在它前面放了inline , 但更多是因为编译器会以这种方式决定。仅将 inline 放入是对编译器的提示)。这可以提高性能,因为编译器现在可以看到参数与函数局部变量匹配的位置,以及参数不相互别名的位置 - 最后但同样重要的是,不再需要函数帧分配。

【讨论】:

  • 完美,谢谢。我尝试输入static 而不是inline
  • 伙计,三年后我才提出自己的问题......现在我在仅标题的实现中有一个数据成员,导致同样的错误。数据成员是static,它在头文件中初始化(但在类声明之外),因为没有实现文件。我该如何解决这个问题(或者我应该问一个新问题)。
  • How to have static data members in a header-only library? 找到它。其中一些愚蠢的 C++ 语言规则有时令人抓狂……
  • 谢谢。添加显式内联也解决了我的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-21
  • 2010-11-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多