J'ai un espace de noms foo
qui contient un entier bar
, déclaré ainsi ...
foo.h:
namespace foo {
int bar;
}
Maintenant, si j'inclus foo.h
dans un seul fichier, cela fonctionne très bien. Mais un problème se pose lorsque j'inclus foo.h
à partir de deux fichiers ou plus: je reçois une erreur de l'éditeur de liens. J'ai compris que si je déclarais bar
comme static
, je pourrais inclure foo.h
dans plusieurs fichiers. Cela me semble étrange, car je ne savais pas que l'on pouvait déclarer une variable statique à l'intérieur d'un espace de noms. (Qu'est ce que ça veut dire?)
Pourquoi ça marche? Et plus important encore, pourquoi ne fonctionne pas cela fonctionne sansstatic
? Que signifie static
quand utilisé dans namespace
?
Il existe plusieurs significations pour static
dans différents contextes. Dans ce contexte particulier, cela signifie que la variable a un lien interne et que chaque unité de traduction qui inclut cet en-tête aura sa propre copie de la variable.
Notez que, même si cela supprime l'erreur de l'éditeur de liens, il conserve une variable foo::bar
distincte pour chacun des fichiers objet générés (les modifications ne seront pas visibles entre différents fichiers objet).
Si vous souhaitez une seule variable, vous devez la déclarer en tant que extern
dans l'en-tête et fournir une définition unique dans une unité de traduction.
Lorsque vous déclarez une variable en tant que static
, cela signifie que son étendue est limitée à l'unité de traduction donnée uniquement. Sans static
, la portée est globale.
Lorsque vous déclarez une variable sous la forme static
dans un fichier .h (au sein ou sans namespace
; peu importe) et que vous incluez ce fichier d'en-tête dans divers fichiers .cpp, la variable static
devient localement étendue à chacun des fichiers .cpp
.
Alors, chaque fichier .cpp contenant cet en-tête aura sa propre copie de cette variable.
Sans le mot clé static
, le compilateur générera une seule copie de cette variable. Ainsi, dès que vous incluez le fichier d'en-tête dans plusieurs fichiers .cpp, l'éditeur de liens se plaindra de plusieurs définitions.
Le problème est causé par plusieurs définitions de la variable. Les définitions dans différentes unités de traduction sont en conflit, tout comme plusieurs définitions de fonction non intégrées ne fonctionneraient pas.
Lorsque vous associez la variable à la variable, vous lui attribuez un lien interne, de sorte que chaque unité de traduction possède sa propre copie indépendante.
Ce que vous voulez probablement, en réalité, est de ne mettre que la déclaration dans un en-tête (en utilisant extern), puis de placer la définition dans un fichier d'implémentation.
Notez également que const int
dans la portée (globale) de l'espace de noms (global) en C++ a static
ajouté implicitement par défaut: Définir des variables constantes dans l'en-tête C++
Pour mieux comprendre ce qui se passe, faites une readelf
sur les fichiers d'objet ELF intermédiaires de la compilation et vous verrez clairement si les symboles sont définis deux fois ou non. Voici un exemple détaillé: Que signifie "statique" en C?