Статическое ключевое слово в файле 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.