En C++, le mot clé static possède deux usages.
Le premier est fortement déconseillé.
Devant une entité déclarée au niveau du fichier (éventuellement dans un namespace), il spécifie que la déclaration est interne à l'unité de compilation.
Cela permet de créer des variables globales internes à une bibliothèque, par exemple.
C'est très aventageusement remplacé par un namespace anonyme (namespace {...}).
L'autre usage est dans une déclaration de classe (ou de structure) ou dans le corps d'une fonction.
Pour expliquer ce static simplement, j'utilise la métaphore du discours.
Le code source est un moyen d'exprimer ce que tu souhaites que fasse un programme (écrit en binaire) généré par le compilateur.
En fait, c'est une suite de demande faite à ce compilateur.
Ainsi, quand j'écris int const x = 2;, ca revient à dire "soit x un entier constant, de valeur 2".
Autre exemple: int f(); se traduit par "supposons une fonction f sans argument et retournant un entier".
Je traduirai en général static en disant "qui n'est pas lié à la durée de vie d'une instance".
Une fonction membre (ou méthode, c'est du vocabulaire) statique n'est pas liée à un objet de la classe. this n'y est pas défini.
Une variable membre statique non plus, c'est une sorte de variable globale, dont le nom est composé du nom complet de la classe puis du sien propre.
1 2 3 4 5
| namespace exemple {
class Bidule{
static int chose;
};
} |
le nom exact de chose est: exemple::Bidule::chose.
Une telle déclaration demande une définition unique (comme toute définition) dans une seule unité de compilation, généralement le .cpp définissant la classe.
Elle s'écrira ainsi:
1 2 3 4 5
| int exemple::Bidule::chose = 4;
//ou
namespace exemple {
int Bidule::chose = 4;
} |
static peut aussi apparaitre dans le corps d'une fonction.
La variable "n'est pas lié à la durée de vie d'une instance" de l'appel de fonction.
considérons cet exemple:
1 2 3 4 5 6 7
| int sequence() {
static int i = 0;
return ++i;
}
int main() {
cout << sequence() << ' ' << sequence() << ' ' << sequence() << endl;
} |
ce programme affichera: "1 2 3".
En effet, au premier appel de sequence, le compilateur entend:
appelle la fonction sequence, c'est à dire:
soit l'entier qui n'est pas lié à la durée de vie d'une instance
retourne la valeur de i pré-incrémentée.
et au second:
appelle la fonction sequence, c'est à dire:
soit l'entier qui n'est pas lié à la durée de vie d'une instance
retourne la valeur de i pré-incrémentée.
Personnellement, je vois i comme la variable (privée) static int sequence()::i. Bien sûr, ca ne compilerait pas comme notation, mais c'est l'idée.
Partager