#c #visual-studio-2017
#c #visual-studio-2017
Вопрос:
Я пишу адаптивный алгоритм обновления размера шага в OpenSees (проект моделирования землетрясений с открытым исходным кодом, написанный в основном в Visual Studio c ). Я столкнулся с конфликтом между двумя переменными, имеющими одинаковое имя в двух разных файлах заголовков (а именно, windef.h и steelz01.h). Мне нужен способ разрешить этот конфликт.
Я использую gnuplot-iostream.h в своем проекте, я сталкиваюсь с этим конфликтом только тогда, когда включаю этот файл заголовка, в противном случае конфликта нет, код собран идеально.
По сути, gnuplot-iostream.h вызывает windows.h, который в дальнейшем вызывает windef.h. Я добавил параметры включения в файл steelz01.h, но это не решило проблему.
Когда я меняю имя varaibale в steelz01.h на другое имя, код также отлично строится. ПРОБЛЕМА не найдена. Но я не хочу указывать имя переменной в steelz01, это имеет серьезные последствия.
Я включаю файлы заголовков, подобные этому
#include "gnuplot-iostream.h"
#include <SteelZ01.h>
Вот как размер переменной определяется в steelz01
#define LOOP_NUM_LIMIT 30
const int SIZE = LOOP_NUM_LIMIT; //limit of array number
и в windef.h это определяется следующим образом
typedef struct tagSIZE
{
LONG cx;
LONG cy;
} SIZE, *PSIZE, *LPSIZE;
typedef SIZE SIZEL;
typedef SIZE *PSIZEL, *LPSIZEL;
Visual Studio 2017 выдает эту ошибку,
1>c:program files (x86)windows kits8.1includesharedwindef.h(190): error C2378: 'SIZE': redefinition; symbol cannot be overloaded with a typedef
1>e:phd working folder0_ops_githubsrcmaterialndreinforcedconcreteplanestresssteelz01.h(17): note: see declaration of 'SIZE'
Я ожидаю способ разрешить этот конфликт и успешную сборку.
Комментарии:
1. Для чего вам нужна переменная
SIZE
для начала? Почему вы не можете использовать макрос? И еще лучше, замените макрос соответствующей постоянной переменной.2. Экспорт переменной с именем just
SIZE
является серьезной проблемой. Это плохой дизайн, с которым другим программистам приходится бороться позже. Решение на C — используйтеnamespace SteelZ01 {
. И не используйте#define
, используйтеstatic constexpr
.3. Как я уже говорил, это проект с открытым исходным кодом (статическая библиотека), авторы steelz01 определили его таким образом. Я могу изменить определение
SIZE
, но проблема в том, что мне нужно изменить имя переменной во всех наследствах steelz014. Затем вы должны сообщить об этом как об ошибке авторам проекта.
5.
#define
это не столько ошибка, сколько то, чего вам следует избегать.#define
вызывает простую замену текста, которая выполняется до начала компиляции компилятором. Везде, гдеLOOP_NUM_LIMIT
существует в коде, он бездумно заменяется на 38. Этот я считаю достаточно безопасным, но в нем нет необходимости.
Ответ №1:
Я бы посоветовал вам поместить оператор include в пространство имен,
namespace ABC
{
#include "gnuplot-iostream.h"
}
namespace PQR
{
#include <SteelZ01.h>
}
Вызов:
ABC::SIZE
PQR::SIZE
Это не изменит никакого кода существующих библиотек. Однако автор библиотеки, использующей общие имена, следовательно, предлагает ему сохранить общее имя в пространстве имен, чтобы уменьшить любой конфликт.
Комментарии:
1. Это интересно. Я буду реализовывать файлы заголовков в пространстве имен и дам вам знать об этом. Большое вам спасибо
2. Это предполагает, что заголовки предоставляют полные определения всего (например, в отдельном исходном файле нет функций, которые, например, могли бы быть предоставлены в виде отдельного объектного файла или библиотеки, и программа не будет связываться с этим подходом).
3. Ни один файл заголовка не содержит только объявлений. У меня есть отдельный файл .cpp, который состоит из всех определений функций-членов. Есть ли у этого подхода к пространству имен какие-либо проблемы??
4. Это будет рассматривать определение и объявление отдельно. Я не думаю, что это создаст проблему.
5. Это действительно плохая идея. Если он компилируется, он сообщает компилятору, что все имена, которые объявлены в этом заголовке, будут определены в этом пространстве имен. Но исходный файл, который определяет эти имена, ничего не знает об этом пространстве имен, и его определений, безусловно, в нем не будет. Не лги компилятору. И, да, если это библиотека «только для заголовков» со всеми встроенными функциями, то она может компилироваться и связываться. Но в результате у вас будет две версии каждой функции, определенной в этом заголовке, одна внутри пространства имен, а другая нет. Удачи в отладке.