Historique de la question
Les membres statiques de classe sont apparus en C++ pour permettre de stocker une valeur ou une fonction commune à tous les objets, sans être liée à une instance spécifique de la classe. Cela est pratique pour stocker, par exemple, des compteurs, des fabriques d'objets ou des fonctions auxiliaires.
Problème
L'une des difficultés a toujours été la portée et le moment de l'initialisation de tels membres, surtout si le programme a de nombreux fichiers sources. Une mauvaise définition d'un membre statique entraîne des erreurs de liaison (linker errors).
Solution
En C++, les membres statiques sont déclarés dans la définition de la classe, mais leur initialisation (pour les variables) doit se faire séparément dans le fichier cpp (avant C++17). C++17 permet l'initialisation directement dans la déclaration, si c'est constexpr.
Exemple de code :
class MyClass { public: static int counter; static void increment() { ++counter; } }; int MyClass::counter = 0; // l'initialisation est OBLIGATOIRE en dehors de la classe
Caractéristiques clés :
Que se passe-t-il si l'on ne définit pas un membre statique dans le fichier cpp ?
Vous obtiendrez une erreur de liaison (linker error), car la variable statique sera déclarée mais non définie. Exception — si static const int est initialisé directement dans la classe pour une valeur constexpr.
// .h class A { public: static int x; }; // .cpp // int A::x = 0; // si commenté — une erreur se produira
Peut-on appeler une fonction non statique depuis une fonction statique ?
Non. La fonction statique n'a pas accès au pointeur this et aux membres non statiques directement. Pour y accéder, un objet spécifique est nécessaire.
class B { int data; static void foo() { // data = 3; // erreur } };
Les variables statiques sont-elles communes à toutes les instances ?
Oui, dans le cadre d'un seul fichier exécutable et d'un processus — la même valeur pour toutes les instances.
Dans l'équipe, ils ont oublié de définir un membre statique dans le fichier cpp, le projet se compile parfois avec une erreur, et parfois, en utilisant l'initialisation inline (pas dans tous les compilateurs), une erreur d'exécution "mystérieuse" apparaît.
Avantages :
Inconvénients :
Dans l'entreprise, il est établi que les membres statiques sont toujours définis dans les fichiers cpp pour chaque classe. Pour la sécurité des threads, des std::mutex ou des opérations atomiques sont utilisées.
Avantages :
Inconvénients :