Статическая переменная в заголовочном файле

Статическая переменная имеет файловую область. Скажем, у меня есть два следующих файла:

  • файл1.h
  • файл1.cpp
  • файл2.h
  • файл2.cpp

Я объявил статическую переменную, скажем, static int Var1 в обоих файлах заголовков. И file1.h, и file2.h включены в файл main.cpp.

Я сделал это, поскольку статическая переменная будет иметь файловую область, поэтому она не будет конфликтовать друг с другом. Но после компиляции я обнаружил, что он показывает конфликт.

Теперь статическая переменная ведет себя как переменная extern. С другой стороны, если я объявлю статическую переменную в обоих файлах .cpp, она хорошо скомпилируется.

Я не могу понять это поведение.

Может ли кто-нибудь объяснить, как масштаб и связь работают в этом сценарии.


person Chris_vr    schedule 18.02.2011    source источник
comment
Связано с этим, см. Не определять безымянное пространство имен в заголовочном файле   -  person jww    schedule 20.02.2018


Ответы (3)


Статические переменные являются локальными для единицы компиляции. Единица компиляции в основном представляет собой файл .cpp с содержимым файла .h, вставленным вместо каждой директивы #include.

Теперь в единице компиляции у вас не может быть двух глобальных переменных с одинаковыми именами. Вот что происходит в вашем случае: main.cpp включает file1.h и file.h, и каждый из двух заголовков определяет свой собственный Var1.

Если логически это две разные переменные, дайте им разные имена (или поместите их в разные пространства имен).

Если это одна и та же переменная, переместите ее в отдельный заголовочный файл, var1.h, и включите var1.h из file1.h и file2.h, не забывая при этом #include guard в var1.h.

person NPE    schedule 18.02.2011

Статические переменные имеют область действия единицы перевода (обычно файл .c или .cpp), но директива #include просто копирует текст файла дословно и не создает другую единицу перевода. После предварительной обработки это:

#include "file1.h"
#include "file2.h"

Превратится в это:

/* file1.h contents */
static int Var1;

/* file2.h contents */
static int Var1;

Что, как известно, недопустимо.

person moatPylon    schedule 18.02.2011
comment
Я думал, что будет две единицы компиляции. Спасибо за устранение сомнений. - person Chris_vr; 22.02.2011

Предположим, что статическая переменная static int Var1 находится в глобальной области видимости в обоих заголовках и включает оба заголовка в main.cpp. Теперь сначала препроцессор копирует содержимое включенных файлов в каталог main.cpp. Поскольку в main.cpp дважды объявлено Var1 в одной и той же области, возникнет ошибка множественного объявления. (т.е. один скопирован из file1.h, а другой из file2.h препроцессором)

Каждый исходный файл компилируется отдельно. Теперь, когда вы объявляете отдельно в своих исходных файлах, каждый исходный файл не знает о существовании другой статической переменной, присутствующей в другом исходном файле с тем же именем. Таким образом, компилятор не сообщает об ошибке. Вы можете пометить его как extern, если хотите, чтобы переменная была общей для исходных файлов.

person Mahesh    schedule 18.02.2011