Static variable, resetting its value to 0, apparently

I have a base class called Component that has several classes derived from it. I want each class to have an integer associated with it (it doesn't matter which component gets what value if they start at 0 and are adjacent). I do not know how to do this directly, so in the same file as Component , I added the following:

 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 

Now I have tested the ComponentID () function and it seems to work fine. Each component class that I tried ComponentID returned a different integer, as I expected. However, when I call ComponentCount, I get 0.

eg. if I have the following lines of code:

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

then my conclusion is:

 0 1 2 0 

I suspect that it happens that the CIDCounter is set to 0 again after it is used to set the cid of each component, but I don’t know for sure, and that seems weird. Is there a way to do what I want, or am I crazy and this whole plan is doomed to failure?

+4
source share
1 answer

You have specified your identifier as static:

 static unsigned int CIDCounter = 0; 

which means that each compilation unit will receive its own copy of the variable. Instead, you should declare it as extern in the header file:

 extern unsigned int CIDCounter; 

and initialize it in the implementation file

 unsigned int CIDCounter = 0; 

It should be noted that without appropriate locks this will not be thread safe.

To clarify:

The static in this context means that a variable or function is limited to the current compilation unit (usually a cpp file). I assume that you have, say, main.cpp and idcounter.cpp , so now we have two variables (one for each compilation unit) main_CIDCounter and idcounter_CIDCounter (variable names are for explanation only!).

When you execute your test code in main.cpp, the template function sees main_CIDCounter , because the current compilation unit and you get the expected 1,2,3. However, when calling ComponentCount() , the code from idcounter.cpp , and this code sees idcounter_CIDCounter - which has not been changed at all. If you had different compilation units, you would see a similar behavior where each cpp file would seem to support its own ID counter.

The fix I described just has only one copy of CIDCounter in idcounter.cpp and declares it as external in all other compilation units.

+9
source

Source: https://habr.com/ru/post/1332200/


All Articles