À l'aide des variables statiques ainsi que les modèles
J'ai un modèle de classe définie dans un fichier d'en-tête comme ça. Ici, j'ai défini une variable statique ainsi:
#ifndef TEST1_H_
#define TEST1_H_
void f1();
static int count;
template <class T>
class MyClass
{
public:
void f()
{
++count;
}
};
#endif
Et j'ai défini la fonction main() dans un autre fichier cpp comme ceci:
int main(int argc, char* argv[])
{
MyClass<int> a;
a.f();
f1();
cout<<"Main:" << count << "\n";
return 0;
}
J'ai implémenté la fonction f1() dans un autre fichier cpp comme ceci:
void f1()
{
MyClass<int> a;
a.f();
cout<<"F1: " <<count <<"\n";
}
Lorsque j'ai compilé ce à l'aide de VC6, j'ai obtenu le résultat que "F1:0 main:2". Comment est-ce possible? Aussi, en général, que dois-je faire si je veux utiliser les variables statiques ainsi que les modèles?
Vous devez vous connecter pour publier un commentaire.
Vous êtes l'obtention de deux copies de la même variable parce que vous avez déclaré une variable statique dans un fichier d'en-tête. Lorsque vous déclarez une variable globale
static
de cette façon, vous dites que c'est local à l'unité de compilation (le.o
fichier). Puisque vous inclure l'en-tête dans deux unités de compilation, vous obtenez deux copies decount
.Je pense que ce que vous voulez vraiment ici est un modèle statique variable de membre associé à chaque instance de la classe de modèle. Il devrait ressembler à ceci:
Ainsi, vous obtenez un nombre pour chaque instanciation de votre modèle. Qui est, vous aurez un compte pour les
MyClass<int>
,MyClass<foo>
,MyClass<bar>
, etc.f1()
serait maintenant ressembler à ceci:Si vous voulez un compte pour les tous les instanciations de MyClass (quel que soit leur modèle de paramètres), vous devez utiliser un variable globale.
Cependant, vous ne voulez probablement pas une variable globale directement parce que vous courez le risque de l'utiliser avant qu'il soit initialisé. Vous pouvez contourner ce problème en faisant un mondial méthode statique qui renvoie une référence à votre compte:
Ensuite y accéder à partir de l'intérieur de votre classe comme ceci:
Cela permettra d'assurer que le comte est initialisé avant d'être utilisé, indépendamment de l'unité de compilation d'y accéder à partir. Voir la C++ FAQ sur la statique de l'ordre d'initialisation pour plus de détails.
Mettre la statique de la déclaration dans un fichier d'en-tête de chaque .fichier cpp pour obtenir sa propre version de la variable. Donc, les deux cout états de l'impression de différentes variables.
C<int>
) puis la nouvelle instance aura une nouvelle statiquecount
Vous attendiez-vous à "F1:1:1"? Vous instancié
MyClass<int>
séparée en deux unités de traduction (c'est à dire deux fichiers objets), et l'éditeur de liens vu qu'il y avait un double instanciation du modèle, de sorte qu'il a rejeté la instanciation qui était enf1
s'objet fichier.Vous êtes de passage
/OPT:ICF
ou/OPT:REF
à la VC6 de l'éditeur de liens? Qui pourrait être liée à la double instanciation du modèle de la suppression (ou pas; dupliquer le modèle instanciations peut-être un cas particulier par rapport à l'ordinaire doublons de fonctions). GCC semble faire quelque chose de similaire sur certaines plates-formes.De toute façon, je ne voudrais pas compter sur ce comportement cohérents à travers les compilateurs. Aussi, de changer l'ordre des fichiers de l'objet sur la ligne de commande liens qui pourrait affecter l'instanciation est rejeté.
Il y a une autre solution, vous pouvez créer un parent commun de la classe et de mettre cette variable statique, alors faites de votre classe de modèle hériter en privé, voici un exemple:
Sortie sera:
Je pense que c'est effectivement comportement indéfini.
En fonction de C++14 [de base.def.odr]/6:
Le problème est que dans le premier
.cpp
fichier, le nomcount
dansf1
fait référence à un autre objet que le nomcount
dansf1
dans la deuxième.cpp
fichier, violant ainsi la condition que les noms se réfèrent à la même entité.Ils sont différents objets en raison de la
static
spécificateur qui dit que chaque unité de traduction devient son propre objet avec ce nom.count
, ou les deux font référence à différentscount
s.