仅具有标头实现的重复符号[重复]

Posted

技术标签:

【中文标题】仅具有标头实现的重复符号[重复]【英文标题】: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。

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

【问题讨论】:

我的猜测是头文件必须是内联函数 【参考方案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++ 语言规则有时令人抓狂…… 谢谢。添加显式内联也解决了我的问题。

以上是关于仅具有标头实现的重复符号[重复]的主要内容,如果未能解决你的问题,请参考以下文章

由于标头中的专业化初始化而避免重复的符号?

架构 x86_64 的重复符号

架构 x86_64 的重复符号(实现 FBSDKCoreKilt)Swift

如果仅重复一组符号,如何使正则表达式匹配?

为啥 XCode 会抛出重复的符号错误?

C ++内联方法实现[重复]