Статическая переменная, по-видимому, сбрасывает свое значение в 0 самостоятельно - PullRequest
4 голосов
/ 15 декабря 2010

У меня есть базовый класс с именем Component, у которого есть несколько классов, полученных из него. Я хочу, чтобы с каждым классом было связано целое число (не имеет значения, какой компонент получает какое значение, если они начинаются с 0 и являются смежными). Я не знаю, как это сделать напрямую, поэтому в тот же файл, что и Component, я добавил следующее:

template <typename T>
class ComponentIdentifier
{
public:
    static unsigned int cid;
};

static unsigned int CIDCounter = 0;
template <typename T> unsigned int ComponentIdentifier<T> = CIDCounter++;

template <typename T> unsigned int ComponentID()
{
    return ComponentIdentifier<T>::cid;
}

unsigned int ComponentCount(); // Defined in .cpp file, just returns CIDCounter

Теперь я протестировал функцию ComponentID (), и она работает нормально. Каждый класс компонента, на котором я пробовал ComponentID, возвращал свое целое число, как я и ожидал. Однако всякий раз, когда я вызываю ComponentCount, я получаю 0.

например. если у меня есть следующие строки кода:

std::cout << ComponentID<AAA>() << std::endl;
std::cout << ComponentID<BBB>() << std::endl;
std::cout << ComponentID<CCC>() << std::endl;
std::cout << ComponentCount() << std::endl;

тогда мой вывод:

0
1
2
0

Я подозреваю, что происходит то, что CIDCounter снова устанавливается в 0 после того, как он используется для установки cid каждого компонента, но я точно не знаю, и это кажется странным. Есть ли способ сделать то, что я хочу, или я сумасшедший, и весь этот план обречен на провал?

1 Ответ

9 голосов
/ 15 декабря 2010

Вы объявили свой идентификатор как статический:

static unsigned int CIDCounter = 0;

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

extern unsigned int CIDCounter;

и инициализировать его в файле реализации

unsigned int CIDCounter = 0;

Следует отметить, что без соответствующих блокировок это не будет потоком-safe.

Для дальнейшего пояснения:

Ключевое слово static в этом контексте означает, что переменная или функция ограничена текущей единицей компиляции (обычно это файл cpp).Я предполагаю, что у вас есть, скажем, main.cpp и idcounter.cpp - так что теперь у нас есть две переменные (по одной для каждой из единиц компиляции) main_CIDCounter и idcounter_CIDCounter (имена переменных только для пояснения!).

Когда вы выполняете свой тестовый код в main.cpp, функция шаблона видит main_CIDCounter, потому что это текущая единица компиляции, и вы получите ожидаемое 1,2,3.Однако при вызове ComponentCount() используется код из idcounter.cpp, и этот код видит idcounter_CIDCounter - который вообще не был изменен.Если бы у вас были другие модули компиляции, вы бы увидели похожее поведение, где каждый файл cpp, похоже, поддерживает свой собственный счетчик идентификаторов.

Исправление, которое я описал, состоит в том, чтобы просто иметь только одну копию CIDCounter вidcounter.cpp и объявить его как внешний для всех остальных модулей компиляции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...