2015-12-10 1 views
4

J'ai une macro que j'utilise pour ajouter une clé, une valeur à une carte de registre. (Supposons que AddToMap se trouve sur un objet statique global qui est défini ailleurs.) La macro AddKey est appelée à différents endroits du code après la définition de différentes classes (une sorte de registre pour les classes). Le code est divisé en plusieurs fichiers .h et .cc avec une dépendance complexe.Membre statique de données dans la fonction statique membre de la classe C++ d'initialisation

Je suit morceau de code qui fonctionne:

#define AddKey(key, val)\ 
namespace NSP_##key {\ 
class A {\ 
    public:\ 
     static bool foo() {\ 
     static bool dummy = AddToMap(#key, #val);\ 
}\ 
};\ 
static bool dummy_A = A::foo();\ 
} 

`

Je veux savoir comment est factice variable statique créé et initialisé. Quand j'utilise GDB, je vois que ce A :: add est appelé bien avant main ou n'importe quoi d'autre s'il est appelé. Ceci est attendu des variables statiques.

Toutefois, si je change de classe pour fonctionner alors le code ne semble pas fonctionner plus et se plaint que « clé a déjà été ajouté »

#define AddKey(key, val)\ 
namespace NS_##key {\ 
    static bool A_foo() {\ 
    static bool dummy = AddToMap(#key, #val);\ 
}\ 
static bool dummy_A = A_foo();\ 
} 

Je comprends que dummy_A doit être statique à cause d'un règle de définition en C++ et même raison pour A_foo(). Mais pourquoi le comportement du mannequin de variable statique est-il différent quand dans la fonction statique par rapport à quand dans le membre statique d'une classe?

+1

Ne vous développez 'AddKey' dans un fichier d'en-tête? – aschepler

+0

oui. GetValue est développé dans le fichier cc et AddKey est développé dans le fichier d'en-tête. –

Répondre

1

Dans une classe, le mot-clé static n'affecte pas le lien, mais signifie qu'il est indépendant des objets de classe. Peu importe combien de fois vous avez AddKey(MyClass, hello), il n'y a qu'une seule fonction NSP_MyClass::A::foo(), qui appelle AddToMap une seule fois.

En dehors d'une classe ou d'une fonction, le mot-clé static donne un nom de liaison interne, ce qui signifie que chaque unité de compilation qui le contient possède sa propre version de ce nom. Donc, dans votre deuxième exemple, il existe une fonction différente appelée NS_MyClass::A_foo() pour chaque fichier * .cc qui comprend AddKey(MyClass, hello). Chacune de ces fonctions essayera d'appeler AddToMap une fois, vous donnant le problème de collision.

Utilisation inline au lieu de static avoir une définition de fonction dans un fichier d'en-tête, mais ont-il vraiment la même fonction à chaque fois:

#define AddKey(key, val)\ 
namespace NS_##key {\ 
    inline bool A_foo() {\ 
     static bool dummy = AddToMap(#key, #val);\ 
    }\ 
    static bool dummy_A = A_foo();\ 
} 
+0

cela semble fonctionner correctement. inline semble s'assurer qu'il s'agit d'une instance unique après tous les fichiers .cc sont liés. Merci –