在我当前的项目中我正在使用arpackpp接口。整个库都是用.h
文件编写的,因此无需编译库。我现在面临的问题 - 当我在一些arpackpp
文件中包含一些main.cpp
头文件时,我收到以下错误:
链接所有/.../ Files / Includes /../../../ arpack ++ / include / arerror.h:163:
ArpackError::Set(ArpackError::ErrorCode, std::string const&)' /.../Files/Includes/../../../arpack++/include/arerror.h:163: first defined here /tmp/ccruWhMn.o: In function
std :: iterator_traits :: iterator_category std :: __ iterator_category的多重定义(char * const&)': /.../Files/Includes/../../../arpack++/include/arerror.h:163:ArpackError::code' /.../Files/Includes/../../../arpack++/include/arerror.h:163: first defined here /tmp/ccruWhMn.o: In function
std :: vector> :: max_size()const'的多重定义:
arpackpp
文件时,有几个.o
函数。正如我在几个线程中读到的那样,问题是我实际上包含了函数的实例化,这通常应该避免。
因为我不想更改整个库,所以使用arpackpp
中的main.cpp
类包含了所有类和函数,这些类变得非常混乱。这个问题有解决方法吗?为什么不包括警卫(#ifndef...#endif)
来防止这个问题?
答案 0 :(得分:0)
首先,包含守卫在这一点上没有帮助,因为它们只能防止在项目文件的依赖图的“子树”中多次包含头部。换句话说:如果在同一项目的两个完全独立的文件中包含一个标头,则c ++预处理器将使用标头中指定的代码将#include <header.h>
两次独立替换。只要标题只包含声明,这就完全没问题。
在您的情况下(以及许多其他仅标题库的情况),标题中也提供了定义。不幸的是(据我所知),除了在项目中包含含有定义的文件之外,没有其他方法。 https://github.com/m-reuter/arpackpp/blob/master/include/README明确说明哪些文件包含定义。
但是,某些库提供了预处理器宏来触发包含所提供头文件的定义(例如https://github.com/nothings/stb)。也许arpackpp
提供了类似的机制。
答案 1 :(得分:0)
通常,使用仅限标头库的最简单方法是仅使用标头扩展代码。如果您使用正确的标头保护,这将消除代码的多个定义问题。如果您有大量现有代码,那么我建议您将所有*.cpp
文件重命名为*.hpp
(c ++头文件),然后添加合适的标头保护。此外,处理此base代码的一种便捷方法是创建一个额外的头文件config.hpp
,并在该文件中包含所有其他头文件。然后在main.c中包含config.hpp
文件就是一件简单的事情。
e.g。
// 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
并链接。