来自重载<<运算符的奇怪链接器错误 - C++

Weird Linker error from overloaded << operator - C++

本文关键字:lt 链接 错误 C++ 重载 运算符      更新时间:2023-10-16

我编写了一个小Timer类来检查代码的性能。源代码可以在这里找到http://pastebin.com/i1PX2VPN(我将在后面强调重要的部分)

现在我遇到了一个非常奇怪的错误:上面链接的代码在一个文件Timer.hpp中。我在main.cpp中使用这个文件,它工作得很好。但是,我还想在另一个源文件中使用它,然后,只要我添加

  #include <Timer.hpp> 

放到下一个源文件中,我得到以下链接器错误:

  ld: duplicate symbol operator<<(std::basic_ostream<char, std::char_traits<char> >&, Timer const&) in /var/folders/XZ/XZ93KWBqG0SR1aCVpTCVQE+++TI/-Tmp-//ccyaHyyU.o and /var/folders/XZ/XZ93KWBqG0SR1aCVpTCVQE+++TI/-Tmp-//ccETAaTw.o
  collect2: ld return 1 as exit status
  make: *** [debugd] Error 1

函数

 std::ostream& operator<<(std::ostream& os, const Timer& t) {
         return os << std::scientific << std::setw(8)  << std::setprecision(3)
                            << t.timeTotal_ << " t " << t.timeMin_ << " t " <<          t.timeMax_;
   }

没有太花哨的…只要它只包含在main.cpp

中,它就可以工作。

显然,这似乎是操作符的多个定义(?)的问题。但我不明白为什么或如何解决它。我使用include-guard来避免它被多次包含。

我已经检查了是否有另一个定时器类在其他任何地方在c++库我从未听说过,这显然不是这种情况(重命名类不会改变任何东西)…

在Timer.hpp中,还定义了另一个类,也有自己的操作符<<过载。我不知道这是否重要,我只是觉得我应该提一下。

所以…我期待着你的想法,谢谢

您应该将函数标记为inline,因为它是一个全局函数,其定义包含在多个翻译单元中。

    inline std::ostream& operator<<(std::ostream& os, const Timer& t) {
//  ^^^^^^
         return os << std::scientific << std::setw(8)  << std::setprecision(3)
               << t.timeTotal_ << " t " << t.timeMin_ << " t " 
               << t.timeMax_;
    }

或者,您可以将函数的声明留在头文件中,并将定义放在单个.cpp文件中。

如果你想知道为什么包含保护不能从多个符号定义中拯救你,你可能会发现这个关于StackOverflow的问题&A很有用。

Include守卫只防止一个文件在同一个翻译单元中被多次包含。如果你把它包含在两个不同的.cpp文件中,你分别编译(.cpp文件通常是),你有多个定义。

把它放在一个实现文件中,只在头文件中留下一个声明。