"множественное определение..." с использованием arpackpp
В моем текущем проекте я работаю с интерфейсом arpackpp. Вся библиотека написана на .h
файлы, так что нет необходимости компилировать библиотеку. Проблема, с которой я сталкиваюсь сейчас - когда я включаю некоторые из arpackpp
заголовочные файлы в некоторых моих файлах, которые не являются main.cpp
Я получаю следующие ошибки:
/.../Files/Include/../../../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)
предотвратить эту проблему?
2 ответа
В общем, самый простой способ работы с библиотеками только с заголовками - это расширение вашего кода только с помощью заголовков. Если вы используете правильные средства защиты заголовков, это устранит проблему множественных определений вашего кода. Если у вас есть большая база существующего кода, я бы предложил переименовать все ваши *.cpp
файлы в *.hpp
(заголовочные файлы C++), а затем добавьте подходящие охранники заголовков. Кроме того, удобный способ обработки этого кода базы - создать дополнительный заголовочный файл. config.hpp
и включите все остальные заголовки в этот файл. Тогда в вашем 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
и ссылка.
Прежде всего, включенные средства защиты не помогают в этом пункте, поскольку они только предотвращают множественные включения заголовка в "поддерево" графа зависимостей файлов вашего проекта. Другими словами: если вы включите заголовок в два полностью разделенных файла одного и того же проекта, препроцессор C++ заменит #include <header.h>
дважды и независимо по коду, указанному в шапке. Это прекрасно, если заголовок содержит только объявления.
В вашем случае (и в случае многих других библиотек только для заголовков) определения также содержатся в заголовках. Так что, к сожалению (насколько я знаю), нет другого элегантного способа, кроме как включить файлы, содержащие определения, один раз в ваш проект. https://github.com/m-reuter/arpackpp/blob/master/include/README прямо указывает, какие файлы содержат определения.
Однако некоторые библиотеки предоставляют макросы препроцессора, чтобы инициировать включение определений для предоставленных заголовочных файлов (например, https://github.com/nothings/stb). Может быть arpackpp
предоставляет аналогичные механизмы.