Un objet comme une fonction, une variable, etc., peut être automatique, dynamique, statique ou externe. Nous connaissons déjà les variables automatiques et dynamiques. Nous nous intéressons ici plutôt aux variables définies en dehors dune fonction, et aux fonctions elles-mêmes.
Si lon souhaite quun tel objet soit utilisable dans tous les fichiers du projet, il faut le déclarer externe
, en utilisant le mot-clé extern
. Si lon préfère que lobjet ne soit utilisable que pour les fonctions du fichier courant, il faut le déclarer statique
avec le mot-clé static
. Les fonctions, définitions de types et variables sont externes par défaut, les constantes statiques.
Imaginons par exemple que le fichier iosfract.cpp
ait besoin de partager avec le programme principal mainfra.cpp
une variable globale glob
(indiquant par exemple la dernière erreur dentrée-sortie produite). Dans ce cas, on nécrira pas, dans le fichier iosfract.h
:
int glob = 1;
sinon la variable serait dupliquée en deux exemplaires différents dans les deux fichiers objets (ce qui nest pas le but recherché), et léditeur de liens signalerait une erreur. Il faut indiquer explicitement au compilateur que la variable glob
est partagée entre deux fichiers objets, et que cest léditeur de liens qui sen occupera. Il faut donc placer dans le fichier den-tête une déclaration externe :
extern int glob;
sans initialisation, et dans lun des deux fichiers objets (nimporte lequel) une déclaration statique avec initialisation (explicite ou implicite puisque les objets statiques sont toujours initialisés) de lobjet :
#include "iosfract.h" int glob = 1; // ...
Ainsi, chaque fois que lon fait référence à glob
dans iosfract.cpp
, le compilateur sait que la variable est en fait ailleurs, et place un lien que léditeur de liens se chargera de résoudre.
Lorsquun objet est externe, il ne doit être initialisé que dans le fichier objet qui le contient effectivement, sinon une erreur est produite. Précisons aussi quune variable peut être déclarée externe à lintérieur dune fonction, bien que ce soit dun intérêt assez faible.
Déclarés en dehors dune fonction, les variables et les types (y compris les classes) sont externes par défaut ; les fonctions également. Elles peuvent être déclarées statiques si elles ne sont utilisées que dans le fichier courant :
static void fonc(void){ ...
Dans ce cas, il est possible à plusieurs fichiers objets davoir une fonction nommée fonc
sans entraîner de conflit, même si les fonctions sont différentes. En fait, léditeur de liens ne connaîtra pas le nom de ces fonctions statiques, qui nest utilisé que par le compilateur et effacé en fin de fichier. La déclaration statique est donc utile pour des fonctions, des variables et des types qui nont pas à être utilisés ailleurs, car elle facilite le travail du compilateur et de léditeur de liens. Noter aussi quune fonction en ligne est inconnue de léditeur de liens (elle est toujours statique).
Les constantes sont statiques par défaut ; de la sorte, deux fichiers objets peuvent utiliser chacun leur version dune constante sans problèmes. Cela permet aussi décrire une constante dans un fichier en-tête et dinclure ce fichier dans plusieurs sources. Une constante peut être déclarée externe, si lon souhaite linitialiser ailleurs. Précisons toutefois que les tableaux constants (y compris les chaînes de caractères) ainsi que les classes et structures constantes sont, eux, externes par défaut (afin déviter une duplication de leur contenu dans les différents fichiers objets).
Les déclarations de types sont externes par défaut. On peut cependant les répéter dans plusieurs fichiers objets, à condition que ce soit de manière identique (en pratique en passant par un fichier en-tête) ; cest ce que nous avons fait avec les types fraction
et matrice_fra
dans notre exemple.
Dune façon générale, on évitera de placer dans un fichier en-tête une définition de fonction (sauf en ligne), de variables (mais une déclaration externe est possible) et de tableaux, classes ou structures constants.
Précédent | Sommaire | Suivant |