"multiple definition of ..." 使用 arpackpp

"multiple definition of ..." using arpackpp

在我当前的项目中,我使用的是 arpackpp 界面。整个库写在 .h 个文件中,因此不需要编译库。我现在面临的问题 - 当我在我的一些文件中包含一些 arpackpp 头文件时,这些文件不是 main.cpp,我得到以下错误:

/.../Files/Includes/../../../arpack++/include/arerror.h:163: multiple definition of ArpackError::Set(ArpackError::ErrorCode, std::string const&)' /.../Files/Includes/../../../arpack++/include/arerror.h:163: first defined here /tmp/ccruWhMn.o: In functionstd::iterator_traits::iterator_category std::__iterator_category(char* const&)': /.../Files/Includes/../../../arpack++/include/arerror.h:163: multiple definition of ArpackError::code' /.../Files/Includes/../../../arpack++/include/arerror.h:163: first defined here /tmp/ccruWhMn.o: In functionstd::vector >::max_size() const':

用于链接所有 .o 文件时的几个 arpackpp 函数。正如我在几个线程中读到的那样,问题是我实际上包括了函数的实例化,这通常应该避免。 因为我不想更改整个库,所以我在 main.cpp 中包含了所有 类 和使用 arpackpp 类 的函数,这变得相当混乱。这个问题有解决方法吗?为什么不包括守卫 (#ifndef...#endif) 来防止这个问题?

首先,include guards 在这一点上没有帮助,因为它们只能防止在项目文件的依赖关系图中的 "subtree" 中多次包含 header。换句话说:如果您在同一项目的两个完全独立的文件中包含 header,C++ 预处理器将替换 #include <header.h> 两次,并且独立地使用 header 中指定的代码。只要 header 只包含声明,这就完全没问题。

对于您的情况(以及许多其他 header-only 库的情况),header 中也提供了定义。所以不幸的是(据我所知),除了在你的项目中包含一次 definition-containing 文件之外,没有其他优雅的方法。 https://github.com/m-reuter/arpackpp/blob/master/include/README 明确指出哪些文件包含定义。

然而,一些库提供预处理器宏来触发包含所提供的 header 文件的定义(例如 https://github.com/nothings/stb)。也许 arpackpp 提供了类似的机制。

一般来说,使用仅 header 库的最简单方法是仅使用 header 扩展您的代码。如果您使用正确的 header 守卫,这将消除您的代码的多个定义的问题。如果您有大量现有代码,那么我建议您将所有 *.cpp 文件重命名为 *.hpp(c++ header 文件),然后添加合适的 header 守卫。此外,处理此基本代码的一种简便方法是创建一个额外的 header 文件 config.hpp 并将所有其他 header 包含在该文件中。然后在您的 main.c 中包含 config.hpp 文件是一件简单的事情。

例如

// Config.hpp ------------------------------------------------=
#include "example.hpp"
#include "example1.hpp"
#include "example2.hpp"
// etc.

// main.cpp --------------------------------------------------=
#include "Config.hpp"

int main() {
  // Your code here.
  return 0;
}

此外,如果您想继续使用您的项目结构,将所有代码分成需要直接访问 arpackcpp 的函数将是一件简单的事情。然后将它们全部包含到一个 *.cpp 文件中,并编译成 *.o 和 link.