2010-09-26 20 views
2

Je me demande pourquoi le nom après la directive #ifndef est toujours tout en majuscules et ne semble pas correspondre au nom du fichier d'en-tête réel? Quelles sont les règles entourant cela? J'ai regardé autour des Webs mais, je n'ai trouvé aucune explication pour ceci. Si mon fichier d'en-tête s'appelle myheader.h, est-il alors possible d'utiliser:C++ #ifndef pour les fichiers d'inclusion, pourquoi toutes les majuscules sont-elles utilisées pour le fichier d'en-tête?

#ifndef MYHEADER 

Si oui, pourquoi? Quelles sont les règles?

Répondre

6

Ce sont des symboles de préprocesseur et n'ont pas de telles règles. (dans la mesure où ils correspondent à #defines dans les en-têtes)

Cependant, la convention consiste à utiliser des majuscules pour les symboles du préprocesseur.

+0

Merci beaucoup! Bien sûr! C'est évident pour moi maintenant, je ne sais pas pourquoi cela ne m'a pas frappé avant. C'est défini après l'ifndef donc .. Ha, merci! – foo

0

Vous pouvez utiliser n'importe quel nom, mais vous voulez le rendre unique afin que la valeur ne soit pas définie en dehors de votre en-tête par hasard, donc l'utilisation du nom d'en-tête avec majuscule est juste une bonne convention.

+0

Merci, tout est clair maintenant. – foo

1

Il n'est pas obligatoire d'utiliser uniquement des majuscules. C'est juste la convention commune. J'utilise habituellement quelque chose comme #ifndef MYHEADER_H_INCLUDED.

+0

Merci, il a finalement cliqué pour moi. Je n'ai juste pas vu (étrangement) que la définition est après l'ifndef. J'ai regardé d'une façon ou d'une autre au mauvais endroit en pensant que le nom de fichier serait résolu en toutes les majuscules ifndef. – foo

1

Google pour "include guard" pour trouver ce que la chose est en fait à propos.

A propos des tous-caps: Il est une convention pour les macros d'être en tout cas supérieur. La raison en est que les macros sont traitées par le préprocesseur, un outil de traitement de texte mystérieux, qui ne connaît rien du C++, et qu'il est préférable de ne pas utiliser d'identifiants communs, de peur de les piétiner, créant un gros désordre.

+0

Oui, je réalise la convention pour les constantes. Mais d'une certaine façon manqué le #define après le #ifndef. – foo

6

Il n'y a pas de "règle", il n'y a que des conventions. La première et la plus utilisée est que toutes les macros de précompilateurs sont en majuscules, donc les gardes d'en-tête devraient être en majuscules. En ce qui concerne le nom de la macro, ce que j'utilise (et ce que la plupart du code que j'utilise) est juste le nom de l'en-tête (comme dit, mis en majuscule) incluant l'extension, en remplaçant le point par souligné, suivi de _INCLUDED.

#ifndef MYHEADER_HPP_INCLUDED 
#define MYHEADER_HPP_INCLUDED 
// ... 
#endif 

Notez que de nombreux PREPEND ces identifiants avec un trait de soulignement ou un double trait de soulignement, mais ce n'est pas une bonne pratique, puisque la norme précise que les identificateurs commençant (ou contenant) doubles underscores et ceux qui commencent par un seul trait de soulignement suivi d'un les majuscules sont réservées aux éléments spécifiques au compilateur/à la bibliothèque (par exemple __declspec dans VC++ ou les macros utilisées dans les en-têtes standard) à tous les champs d'application; tous les autres identifiants commençant par un seul trait de soulignement sont réservés à l'étendue globale. Donc, de tels identifiants ne devraient pas être utilisés pour éviter les collisions.

Plus d'informations sur ce produit here.

1

L'idée est de s'assurer que votre fichier d'en-tête n'est lu qu'une seule fois lors de la construction. L'idiome pour y parvenir est la structure:

#ifndef _SOME_UNIQUE_NAME 
    #define _SOME_UNIQUE_NAME 
    /* The actual header code */ 
    #endif 

Cela signifie que vous devez choisir un nom que vous êtes assez sûr sera unique et est un identifiant valide pour #ifndef. Vous devez également vous assurer que l'identifiant n'est pas utilisé dans le code réel ou confondu avec une variable ou quelque chose. Avoir une étiquette majuscule marque clairement l'idiome.En outre, ce ne sont que les conventions et non le langage qui dictent ce choix. Les assistants de Visual Studio génèrent un identifiant similaire à GUID pour. Les compilateurs Sone supportent #pragma une fois qui ont le même effet.

+1

Évitez les caractères de soulignement dans les protecteurs d'en-tête (et, en général, pour les identificateurs, lorsqu'ils sont suivis d'une lettre majuscule); voir ma réponse pour plus de détails. –

0

C'est complètement subjectif et il n'y a pas de règles imposées autres que celles normalement associées au jeu de caractères pour nommer les macros pré-processeur. C'est classique pour les macros à définir en majuscules. Cela tend à les aider à se démarquer dans le code source. Une convention à laquelle j'ai tendance à adhérer est la version strictement capitalisée du nom de fichier, la période étant remplacée par un trait de soulignement et des caractères de soulignement avant et arrière. Ainsi, pour un fichier appelé DataTableNameMangler.hpp include garde ressemblerait à ceci:

#ifndef _DATATABLENAMEMANGLER_HPP_ 
#define _DATATABLENAMEMANGLER_HPP_ 

... 

#endif // _DATATABLENAMEMANGLER_HPP_ 

Il n'y a pas grande raison de ce que je recommande fortement la cohérence que le nom correspond au nom de fichier exactement. J'utilise normalement un petit script de création de classe pour générer mes classes initiales. Ce qui suit extrait Bash donne une idée:

#!/bin/bash 
INC_GUARD_NAME="_${1^^*}_HPP_" 
echo "#ifndef $INC_GUARD_NAME" 
echo "#ifndef $INC_GUARD_NAME" 
echo 
echo "class $1 {};" 
echo 
echo "#endif // $INC_GUARD_NAME" 

Ainsi:

$ ./makeclass.bash DataTableNameMangler 
#ifndef _DATATABLENAMEMANGLER_HPP_ 
#ifndef _DATATABLENAMEMANGLER_HPP_ 

class DataTableNameMangler {}; 

#endif // _DATATABLENAMEMANGLER_HPP_ 

Ceci est naturellement juste un exemple très basique. Surtout, n'oubliez pas de mettre le commentaire avant le nom de garde sur la dernière ligne. #endif ne prend aucun paramètre donc la macro sera transmise au compilateur C++ qui s'en plaindra s'il n'est pas commenté.

+2

Évitez les caractères de soulignement dans les protecteurs d'en-tête (et, en général, pour les identificateurs, lorsqu'ils sont suivis d'une lettre majuscule); voir ma réponse pour plus de détails. –