Статическое ключевое слово в файле h и внутренняя связь
Еще один вопрос static
.
Я прочитал следующее:
И я все еще не понимаю следующее поведение:
У меня есть один файл h
:
// StaticTest.h
#include <stdio.h>
static int counter = 0;
struct A {
A () {
counter++;
printf("In A ctor(%d)\n", counter);
}
~A () {
counter--;
printf("In A dtor(%d)\n", counter);
}
};
static A a;
И два файла cpp
:
// StaticTest1.cpp
#include "StaticTest.h"
int main () {
return 0;
}
и
// StaticTest2.cpp
#include "StaticTest.h"
Вывод программы:
In A ctor(1)
In A ctor(2)
In A dtor(1)
In A dtor(0)
Теперь конструктор A
вызывается дважды, так как файл h
включен дважды, а поскольку экземпляр A
с именем A
объявлен static
, он имеет внутреннюю связь и компилятор счастлив.
Поскольку counter
также объявлен статическим, он также имеет внутреннюю связь, и я ожидал бы, что это значение не будет использоваться в двух файлах cpp
--- но вывод программы подразумевает, что значение является общим, поскольку оно подсчитывается до 2.
какие-нибудь идеи?
EDIT:
Также приветствуются любые ответы на то, что считается "хорошей привычкой программирования" в контексте объявления статических переменных в файлах h
и cpp
.
Ответы
Ответ 1
Если StaticTest.h
разделяется между исходными файлами различий, вы получите поведение undefined.
Если вы определяете класс или встроенные функции в разных единицах перевода, то их определения должны быть одинаковыми (одна и та же последовательность токенов), и, что важно, любые идентификаторы должны ссылаться на одну и ту же сущность (если только объект const
с внутренней связью), как в определении в другой единицы перевода.
Вы нарушаете это, потому что counter
имеет внутреннюю связь, поэтому в разных единицах перевода идентификатор в определениях функций относится к другому объекту.
Ссылка: С++ 03 3.2 [basic.def.odr]/5.