Les fonctions et variables membres hors classe
- Les fonctions ou varibales marquées
inline(privilège introduit en C++17 pour les variables) sont stockées globalement dans une seule instance ; - Les éléments marqués
staticsont chacun copiés dans chaque unité de compilation ; - Les variables statiques locales dans des fonctions
staticont plusieurs copies, tandis que celles dans des fonctionsinlinen'en ont qu'une seule ; - Une déclaration combinée
static inlinea le même effet qu’un simplestatic; - Le mot-clé
inlinene peut pas être utilisé sur des variables locales.
Les membres fonctionnels et variables au sein d'une classe
- Depuis C++17, les variables statiques non constantes peuvent être initialisées directement à l'intérieur de la déclaration de la classe grâce à
static inline. Avant C++17, cette initialisation devait obligatoirement se faire en dehors de la classe ; - En C++17, si une variable statique de classe est déclarée avec
static inline, son initialisation en tête de fichier (dans un .h) ne provoque plus d'erreur de redéfinition. Sansinline, cela entraîne une duplication entre les unités de compilation, causant des erreurs liées au lien ; - Avant C++17, toute initialisation d'une variable statique de classe dans un fichier d'en-tête conduisait à une erreur de redéfinition. Il fallait donc la placer dans un fichier source (.cpp) pour éviter ce problème ;
- En réalité, toutes les fonctions membres d'une classe sont implicitement traitées comme
inline, car elles sont définies globalement une seule fois. La présence ou non destaticne change pas leur localisation, mais seulement leur accès aux membres : les fonctionsstaticn'accèdent qu'aux membres statiques, tandis que les fonctions normales peuvent accéder à tous les membres.
Pourquoi les variables statiques non constantes étaient-elles interdites en initialisation directe dans la classe avant C++17 ?
- Les variables statiques appartiennent à la classe, pas à une instance. Si elles étaient initialisées directement dans la définition de la classe, chaque objet construit aurait réinitialisé cette variable, entraînant des comportements imprévisibles ;
- Les variables statiques constantes, quant à elles, pouvaient être initialisées à l’intérieur de la classe car elles ne changent jamais après leur construction — leur valeur est figée dès la compilation ;
- Avant C++17, il était strictement interdit d’initialiser une variable statique non constante dans la déclaration de la classe. Toute tentative d’initialisation dans un fichier d’en-tête provoquait une erreur de redéfinition lors du lien ;
- Avec C++17, l’introduction de
inlinepour les membres statiques permet d’assurer qu’une seule copie existe globalement. Grâce à cette sémantique, une variable statique peut être déclarée et intiialisée directement dans la classe, ou déclarée dans la classe et initialisée viainlinedans un fichier d’en-tête. Cela garantit une initialisation unique et partagée.
Exemple concret illustratif
Phase 1
main.cpp
#include "test.h"
#include "test2.h"
int main() {
return 0;
}
test.h
bool flag = true;
test2.h
#include "test.h"
Résultat de la compilation :
Erreur C2374 : « flag » redéfini ; initialisation multiple
Phase 2
Modification de test.h :
#pragma once
bool flag = true;
Résultat du lien :
Erreur LNK2005 : « bool flag » déjà définie dans test.obj
Phase 3
Modification de test.h :
#pragma once
inline bool flag = true;
Résultat :
Génération réussie : 1 succès, 0 échecs
Ce cas montre clairement un usage typique des variables inline : éviter les conflits de redéfinition dans les fichiers d’en-tête.
On peut aussi déplacer la définition dans un fichier .cpp, ce qui aurait eu le même effet positif.