ifndef, define, endif

204
08 февраля 2018, 17:10

Я не понимаю, то ли я криворук, то ли лыжи не скачут.

Файл C.h

#ifndef C_H
#define C_H
int QWE = 1;
#endif /* C_H */

Файл B.h

#include "C.h"

Файл A.h

#include "B.h"

Почему компилятор ругается на LNK2005 "int QWE" (?QWE@@3HA) уже определен в A.obj, если были использованы ifndef, define, endif? Пробовал качать другую версию MSVS, пробовал писать #pragma once, но ошибка остаётся. Ткните носом, где я туплю?

Answer 1

Вы подключаете (пусть опосредованно) c.h в разные .cpp-файлы, вот у вас и получается в двух разных файлах определение

int QWE = 1;

Вот линковщик и ругается, встречая две переменные с одним именем в двух разных местах, не зная, что ему выбрать...

Объявите переменную в .h-файле как

extern int QWE;

а в одном .cpp-файле определите

int QWE = 1;

Так вы перестанете нарушать правило одного определения.

Answer 2

Назначение include guards #ifndef/#define/#endif - защитить ваш код от ошибок вида

#include "C.h"
...
#include "C.h"

т.е. от множественного включения одного и того же заголовка в одну и ту же единицу трансляции (явно или опосредованно, через другие заголовки). Такое множественное включение в общем случае приведет к ошибкам компиляции.

Include guards, вопреки вашим ожиданиям, не имеют никакого отношения к защите от ошибок множественного определения переменных или функций во всей программе, т.е. между разными единицами трансляции (вызывающих ошибки линковки). От вашей ошибки include guards никак не защищают и не должны защищать, поэтому ваше удивление "Почему компилятор ругается на LNK2005, ... если были использованы ifndef, define, endif?" совершенно не оправданно.

Либо перестаньте совать определения переменных в заголовочный файл (т.е. пойдите по "классическому" пути с extern). Либо воспользуйтесь свойством С++17 и просто сделайте вашу переменную inline

#ifndef C_H
#define C_H
inline int QWE = 1;
#endif /* C_H */
READ ALSO
Метод Delete. Обертка над массивом. Неверный алгоритм

Метод Delete. Обертка над массивом. Неверный алгоритм

У меня есть некий класс, который является оберткой над массивомЭтот класс называется хранилищем моих элементов

228
Взаимодействие php и java (не js)

Взаимодействие php и java (не js)

Есть программа, большую часть своей жизни она сидит в трее и должна иногда мигать иконкой, при двойном клике открывать вебкитМигает она или...

189
Как записать данные из переменной в файл?

Как записать данные из переменной в файл?

Как записать данные из double probinres в FILENAME?

210
Вылетает приложение. Работа с sqlite

Вылетает приложение. Работа с sqlite

Почему вылетает приложениеНачинаю работать с sqlite, простой вывод данных бд в listView не работет - приложение просто вылетает

197