En C++, il est courant de nommer les variables membres avec une sorte de préfixe pour indiquer le fait qu'il s'agit de variables membres, plutôt que de variables locales ou de paramètres. Si vous venez d'un arrière-plan MFC, vous utiliserez probablement m_foo
. J'ai aussi vu myFoo
de temps en temps.
C # (ou peut-être simplement .NET) semble recommander l'utilisation d'un trait de soulignement, comme dans _foo
. Est-ce autorisé par le standard C++?
Les règles (qui n'ont pas changé en C++ 11):
std
est réservé. (Vous êtes cependant autorisé à ajouter des spécialisations de modèles.)À partir de la norme C++ 2003:
17.4.3.1.2 Noms globaux [lib.global.names]
Certains ensembles de noms et de signatures de fonctions sont toujours réservés à la mise en oeuvre:
- Chaque nom qui contient un double trait de soulignement (
__
) ou commence par un trait de soulignement suivi d'une lettre majuscule (2.11) est réservé à la mise en oeuvre pour toute utilisation.- Chaque nom commençant par un trait de soulignement est réservé à l'implémentation pour pouvoir être utilisé comme nom dans l'espace de noms global.165
165) Ces noms sont également réservés dans l'espace de noms
::std
(17.4.3.1).
Comme C++ est basé sur le standard C (1.1/2, C++ 03) et que C99 est une référence normative (1.2/1, C++ 03), ceux-ci s'appliquent également, à partir du standard C de 1999:
7.1.3 Identifiants réservés
Chaque en-tête déclare ou définit tous les identificateurs répertoriés dans sa sous-clause associée et éventuellement identifie ou définit les identificateurs répertoriés dans sa sous-clause d'instructions de bibliothèque future associée et les identificateurs qui sont toujours réservés pour toute utilisation ou pour être utilisés comme identificateurs de portée de fichier.
- Tous les identificateurs commençant par un trait de soulignement et une lettre majuscule ou un autre trait de soulignement sont toujours réservés pour toute utilisation.
- Tous les identificateurs commençant par un trait de soulignement sont toujours réservés à une utilisation en tant qu'identificateurs avec une étendue de fichier dans les espaces de nom de balise et ordinaire.
- Chaque nom de macro dans l’un des sous-paragraphes suivants (y compris les instructions futures de la bibliothèque) est réservé pour une utilisation spécifiée si l’un des en-têtes associés est inclus; sauf indication explicite contraire (voir 7.1.4).
- Tous les identifiants avec une liaison externe dans l’un des sous-paragraphes suivants (y compris les instructions futures de la bibliothèque) sont toujours réservés à une utilisation en tant qu’identifiants avec une liaison externe.154
- Chaque identifiant avec une étendue de fichier répertoriée dans l’un des sous-paragraphes suivants (y compris les instructions futures de la bibliothèque) est réservé à l’utilisation en tant que nom de macro et en tant qu’identifiant avec une étendue de fichier dans le même espace de nom si l’un des en-têtes associés est inclus.
Aucun autre identifiant n'est réservé. Si le programme déclare ou définit un identifiant dans un contexte dans lequel il est réservé (autre que celui autorisé par 7.1.4), ou définit un identifiant réservé en tant que nom de macro, le comportement est indéfini.
Si le programme supprime (avec
#undef
) toute définition de macro d'un identificateur du premier groupe répertorié ci-dessus, le comportement n'est pas défini.154) La liste des identificateurs réservés avec une liaison externe comprend
errno
,math_errhandling
,setjmp
etva_end
.
D'autres restrictions peuvent s'appliquer. Par exemple, la norme POSIX réserve de nombreux identifiants susceptibles d'apparaître dans le code normal:
E
suivaient un chiffre ou une lettre majuscule: is
ou to
suivi d'une lettre minuscule LC_
suivi d'une lettre majuscule f
ou l
sont réservés SIG
suivi d'une lettre majuscule sont réservés SIG_
suivi d'une lettre majuscule sont réservés str
, mem
ou wcs
suivi d'une lettre minuscule sont réservés PRI
ou SCN
suivi de toute lettre minuscule ou X
sont réservés _t
sont réservés L'utilisation de ces noms pour vos propres besoins actuels ne pose aucun problème, mais il existe un risque de conflit avec les versions futures de cette norme.
Personnellement, je ne commence pas les identifiants avec des traits de soulignement. Nouvel ajout à ma règle: n'utilisez pas de double soulignement n'importe où, ce qui est facile, car j'utilise rarement le soulignement.
Après avoir effectué des recherches sur cet article, je ne termine plus mes identifiants avec _t
car celui-ci est réservé par le standard POSIX.
La règle concernant tout identifiant se terminant par _t
m'a beaucoup surpris. Je pense que c’est un standard POSIX (pas encore sûr) qui cherche une clarification, un chapitre et un vers officiels. Ceci est tiré du manuel de la librairie GN , listant les noms réservés.
CesarB a fourni le lien suivant vers les symboles et notes réservés POSIX 2004 "que de nombreux autres préfixes et suffixes réservés ... peuvent y être trouvés". Les symboles réservés POSIX 2008 sont définis ici. Les restrictions sont un peu plus nuancées que celles ci-dessus.
Les règles pour éviter la collision de noms sont à la fois dans la norme C++ (voir le livre de Stroustrup) et mentionnées par les gourous de C++ (Sutter, etc.).
Parce que je ne voulais pas traiter de cas et que je voulais une règle simple, j'ai conçu un personnel à la fois simple et correct:
En nommant un symbole, vous éviterez les conflits avec les bibliothèques du compilateur/OS/standard si vous:
Bien sûr, placer votre code dans un espace de noms unique permet également d'éviter les conflits (sans vous protéger contre les macros diaboliques).
(J'utilise des macros car ce sont les symboles C/C++ qui polluent le plus en code, mais cela peut aller de nom de variable à nom de classe)
#define _WRONG
#define __WRONG_AGAIN
#define RIGHT_
#define WRONG__WRONG
#define RIGHT_RIGHT
#define RIGHT_x_RIGHT
A partir du fichier n3242.pdf (j'attends que le texte standard final soit similaire):
17.6.3.3.2 Noms globaux [noms.globaux]
Certains ensembles de noms et de signatures de fonctions sont toujours réservés à la mise en oeuvre:
- Chaque nom contenant un double trait de soulignement _ _ ou commençant par un trait de soulignement suivi d'une lettre majuscule (2.12) est réservé à la mise en oeuvre pour toute utilisation.
- Chaque nom commençant par un trait de soulignement est réservé à l'implémentation pour pouvoir être utilisé comme nom dans l'espace de noms global.
Mais aussi:
17.6.3.3.5 Suffixes littéraux définis par l'utilisateur [usrlit.suffix]
Les identificateurs de suffixe littéral qui ne commencent pas par un trait de soulignement sont réservés pour la normalisation future.
Cette dernière clause est source de confusion, sauf si vous considérez qu'un nom commençant par un trait de soulignement et suivi d'une lettre minuscule serait Ok si ne pas défini dans l'espace de noms global ...
De MSDN :
L'utilisation de deux caractères de soulignement séquentiels (__) au début d'un identificateur, ou d'un soulignement simple suivi d'une lettre majuscule, est réservée aux implémentations C++ dans toutes les portées. Vous devez éviter d'utiliser un trait de soulignement suivit d'une lettre minuscule pour les noms avec une étendue de fichier en raison de conflits éventuels avec les identificateurs réservés actuels ou futurs.
Cela signifie que vous pouvez utiliser un simple trait de soulignement comme préfixe de variable membre, à condition qu'il soit suivi d'une lettre minuscule.
Ceci est apparemment tiré de la section 17.4.3.1.2 de la norme C++, mais je ne trouve pas de source originale pour la norme complète en ligne.
Voir aussi cette question .
Pour ce qui est de l’autre partie de la question, il est courant de mettre le trait de soulignement à la fin du nom de la variable afin de ne pas entrer en conflit avec quelque chose d’interne.
Je le fais même à l'intérieur de classes et d'espaces de noms car je n'ai alors plus qu'à mémoriser une règle (par opposition à "à la fin du nom dans la portée globale et au début du nom partout ailleurs").
Oui, les traits de soulignement peuvent être utilisés n'importe où dans un identifiant. Je crois que les règles sont les suivantes: a-z, A-Z, _ dans le premier caractère et ceux + 0-9 pour les caractères suivants.
Les préfixes de soulignement sont courants dans le code C: un soulignement simple signifie "privé", et les soulignements doubles sont généralement réservés au compilateur.