Почему это происходит, если у меня установлены охранники? Я думал, что они препятствуют тому, чтобы заголовок был прочитан после первого доступа.
Включите охрану, убедитесь, что заголовок включен только один раз в один файл (единица перевода). Для нескольких файлов, включая заголовок, вы хотите, чтобы заголовок был включен в каждый файл.
Путем определения , в отличие от объявления переменных с внешней связью (глобальными переменными) в вашем заголовочном файле, вы можете включить заголовок только в один исходный файл. Если вы включите заголовок в несколько исходных файлов, будет несколько определений переменной, что недопустимо в C ++.
Итак, как вы выяснили, неправильно определять переменные в заголовочном файле именно по указанной выше причине.
Почему многочисленные перечисления в этом заголовке также не дают предупреждений LNK4006?
Потому что они не определяют «глобальные переменные», они являются только объявлениями о типах и т. Д. Они не резервируют никакого хранилища.
Если я добавлю статический элемент перед подписью, я не получу предупреждение. Каковы последствия того, чтобы делать это таким образом.
Когда вы создаете переменную static
, она имеет статическую область действия . Объект не виден за пределами единицы перевода (файла), в которой он определен. Итак, простыми словами, если у вас есть:
static int i;
в вашем заголовке, каждый исходный файл, в который вы включаете заголовок, получит отдельную int
переменную i
, которая невидима вне исходного файла. Это известно как внутренняя связь .
Есть ли лучший способ сделать это, чтобы избежать ошибки, но позвольте мне объявить массив в заголовке. Я бы очень не хотел иметь файл cpp только для определения массива.
Если вы хотите, чтобы массив был одним объектом, видимым из всех ваших файлов C ++, вы должны сделать:
extern int array[SIZE];
в вашем файле заголовка, а затем включите файл заголовка во все исходные файлы C ++, которым требуется переменная array
. В одном исходных (.cpp
) файлах необходимо определить array
:
int array[SIZE];
Вы также должны включить заголовок в приведенный выше исходный файл, чтобы можно было обнаруживать ошибки из-за разницы в заголовке и исходном файле.
По сути, extern
сообщает компилятору, что "array
определено где-то и имеет тип int
и размер SIZE
". Затем вы на самом деле определяете array
только один раз. На этапе соединения все разрешается красиво.