7

我有一个在头文件中声明和实现的 C++ 类。_GLIBCXX_DEBUG我之所以选择这个,是因为由于预编译的库,人们无法在 Debug 和 Release 版本之间轻松移动。例如,如果我定义_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)编译并链接正常。

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

4

1 回答 1

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

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

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

于 2012-11-19T04:03:01.770 回答