2010-12-15 52 views
4

J'ai une classe de base appelée Component qui a un certain nombre de classes dérivées. Je veux que chaque classe soit associée à un entier (peu importe quel composant obtient quelle valeur, tant qu'ils commencent à 0 et sont contigus). Je ne sais pas comment faire cela directement, donc dans le même fichier que je Component ajouté ce qui suit:Variable statique réinitialisant sa valeur à 0 par elle-même apparemment

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 

Maintenant, je testé la fonction ComponentID() et il semble fonctionner très bien. Chaque classe de composant sur laquelle j'ai essayé ComponentID a retourné un entier différent comme je le pensais. Cependant, chaque fois que j'appelle ComponentCount, j'obtiens 0.

par exemple. si j'ai les lignes de code suivantes:

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

alors ma sortie est:

0 
1 
2 
0 

je soupçonne que ce qui se passe est que CIDCounter est réglé sur 0 à nouveau après son utilisé pour définir de la cid de chaque composante, mais je ne sais pas à coup sûr et cela semble un peu bizarre. Y at-il un moyen de faire ce que je veux ou suis-je folle et tout ce plan voué à l'échec?

Répondre

9

Vous avez déclaré votre identifiant comme statique:

static unsigned int CIDCounter = 0; 

qui signifie que chaque unité de compilation aura sa propre copie de la variable. Au lieu de cela, vous devez le déclarer comme extern dans le fichier d'en-tête:

extern unsigned int CIDCounter; 

et initialisez dans le fichier de mise en œuvre

unsigned int CIDCounter = 0; 

Il faut noter que, sans verrous appropriés ce ne sera pas thread-safe.

Pour être plus précis:

Le mot-clé static dans ce contexte signifie que la variable ou la fonction est limitée à l'unité de compilation en cours (généralement un fichier cpp). Je suppose que vous avez, disons, un main.cpp et un idcounter.cpp - donc maintenant nous avons deux variables (une pour chacune des unités de compilation) main_CIDCounter et idcounter_CIDCounter (les noms de variables sont pour l'explication seulement!).

Lorsque vous exécutez votre code de test dans main.cpp, la fonction de modèle voit main_CIDCounter car c'est l'unité de compilation actuelle et vous obtenez le 1,2,3 attendu. Cependant, lorsque vous appelez le ComponentCount() code idcounter.cpp est utilisé, et ce code voit idcounter_CIDCounter - qui n'a pas été modifié du tout. Si vous aviez d'autres unités de compilation, vous verriez un comportement similaire, où chaque fichier cpp semblerait conserver son propre compteur d'ID.

La correction que j'ai décrite est simplement de n'avoir qu'une copie de CIDCounter dans idcounter.cpp, et de la déclarer comme externe dans toutes les autres unités de compilation.

+0

Merci, ça l'a fait. – Alex