web-dev-qa-db-fra.com

Conventions de dénomination des variables en C ++

Je viens d'un monde .NET et je suis novice en écriture C++. Je me demande simplement quelles sont les conventions de dénomination préférées lorsqu'il s'agit de nommer des variables locales et des membres de structure.

Par exemple, le code hérité dont j'ai hérité en contient beaucoup:

struct MyStruct
{
   TCHAR           szMyChar[STRING_SIZE];
   bool            bMyBool;
   unsigned long   ulMyLong;
   void*           pMyPointer;
   MyObject**      ppMyObjects;
}

Venant d'un arrière-plan C #, j'ai été choqué de voir les variables avec la notation hongroise (je ne pouvais pas m'arrêter de rire du préfixe pp la première fois que je l'ai vu).

Je préfère de loin nommer mes variables de cette façon (même si je ne suis pas sûr que la mise en majuscule de la première lettre soit une bonne convention. J'ai vu d'autres façons (voir les liens ci-dessous)):

struct MyStruct
{
   TCHAR           MyChar[STRING_SIZE];
   bool            MyBool;
   unsigned long   MyLong;
   void*           MyPointer;
   MyObject**      MyObjects;
}

Ma question: est-ce (l'ancienne méthode) toujours une façon préférée de nommer les variables en C++?

Les références:

http://geosoft.no/development/cppstyle.html

http://www.syntext.com/books/syntext-cpp-conventions.htm

http://ootips.org/hungarian-notation.html

Merci!

33
stung

Ce type de notation hongroise est assez inutile, et peut-être pire qu'inutile si vous devez changer le type de quelque chose. ( Le type de notation hongroise est une autre histoire.)

Je vous suggère d'utiliser ce que fait votre groupe. Si vous êtes la seule personne à travailler sur le programme, nommez-les de la manière qui vous convient le mieux.

55
Head Geek

La chose la plus importante est d'être cohérent. Si vous travaillez avec une base de code héritée, nommez vos variables et fonctions de manière cohérente avec la convention de dénomination du code hérité. Si vous écrivez du nouveau code qui ne fait qu'interfacer avec l'ancien code, utilisez votre convention de dénomination dans le nouveau code, mais soyez également cohérent avec vous-même.

16
Adam Rosenfield

Non. La "mauvaise notation hongroise" - en particulier le pp pour la double indirection - avait un certain sens pour les premiers compilateurs C où vous pouviez écrire

int * i = 17;
int j = ***i;

sans même un avertissement du compilateur (et cela pourrait même être du code valide sur le bon matériel ...).

La "vraie notation hongroise" (telle que liée par le chef Geek) est l'OMI toujours une option valide, mais pas nécessairement préférée. Une application C++ moderne a généralement des dizaines ou des centaines de types, pour lesquels vous ne trouverez pas de préfixes appropriés.

Je l'utilise toujours localement dans quelques cas où je dois mélanger par exemple variables entières et flottantes qui ont des noms très similaires ou même identiques dans le domaine problématique, par ex.

float fXmin, fXmax, fXpeak; // x values of range and where y=max
int   iXmin, iXMax, iXpeak; // respective indices in x axis vector

Cependant, lorsque vous maintenez un code hérité qui suit certaines conventions de manière cohérente (même si de manière lâche), vous devez vous en tenir aux conventions utilisées là-bas - au moins dans les modules/unités de compilation existants à maintenir.

Mon raisonnement: Le but des normes de codage est de respecter le principe de la moindre surprise. L'utilisation d'un style de manière cohérente est plus importante que le style que vous utilisez.

15
peterchen

Qu'est-ce qui n'aime pas ou se moque de "ppMyObjects" dans cet exemple, à part qu'il soit quelque peu moche? Je n'ai pas d'opinions fortes de toute façon, mais il communique des informations utiles en un coup d'œil que "MyObjects" n'a pas.

6
xyz

Je suis d'accord avec les autres réponses ici. Soit continuer à utiliser le style qui vous est donné par la main pour des raisons de cohérence, soit proposer une nouvelle convention qui fonctionne pour votre équipe. Il est important que l'équipe soit d'accord, car il est presque garanti que vous changerez les mêmes fichiers. Cela dit, certaines choses que j'ai trouvées très intuitives dans le passé:

Les variables membres de classe/struct doivent se démarquer - je les préfixe généralement toutes avec m_
Les variables globales doivent se démarquer - préfixe usuel avec g_
Les variables en général doivent commencer par des minuscules
Les noms de fonction en général doivent commencer par des majuscules
Les macros et éventuellement les énumérations doivent être en majuscules
Tous les noms doivent décrire ce que fait la fonction/variable et ne doivent jamais décrire son type ou sa valeur.

4
Marcin

Je suis moi-même un utilisateur de la notation hongroise, car je trouve que cela donne de la lisibilité au code, et je préfère de loin le code auto-documenté aux commentaires et aux recherches.

Cela dit, je pense que vous pouvez plaider en faveur du sacrifice de votre style préféré et d'une certaine maintenabilité supplémentaire pour l'unité de l'équipe. Je n'achète pas l'argument de la cohérence pour une lisibilité uniforme du code, surtout si vous réduisez la lisibilité pour la cohérence ... cela n'a tout simplement pas de sens. Cependant, s'entendre avec les personnes avec lesquelles vous travaillez pourrait valoir un peu plus de confusion sur les types qui examinent les variables.

2
Nick

Tout dépend de vos préférences personnelles. J'ai travaillé pour 2 entreprises avec des schémas similaires, où les variables membres sont nommées m_varName. Je n'ai jamais vu de notation hongroise utilisée au travail, et je n'aime vraiment pas ça, mais encore une fois, de préférence. Mon sentiment général est que les IDE devraient prendre soin de vous dire de quel type il s'agit, donc tant que le nom est suffisamment descriptif de ce qu'il fait (m_color, m_shouldBeRenamed), alors c'est ok. L'autre chose que j'aime est une différence entre la variable membre, la variable locale et la dénomination constante, donc il est facile de voir ce qui se passe dans une fonction et d'où viennent les variables. Membre: m_varName Const: c_varName local: varName

1
DavidG

La notation hongroise était courante parmi les utilisateurs des API Win32 et MFC. Si vos prédécesseurs l'utilisaient, vous pouvez probablement continuer à l'utiliser (même si ça craint). Le reste du monde C++ n'a jamais eu cette convention mortelle, alors ne l'utilisez pas si vous utilisez autre chose que ces API.

1
Leon Timmermans

Je pense que vous trouverez toujours que la plupart des magasins qui programment en Visual C++ s'en tiennent à la notation hongroise ou au moins une version édulcorée de celui-ci. Dans notre boutique, la moitié de notre application est l'héritage C++ avec une nouvelle couche C # brillante sur le dessus (avec une couche C++ gérée au milieu.) Notre code C++ continue d'utiliser la notation hongroise mais notre code C # utilise la notation comme vous l'avez présenté. Je pense que c'est moche, mais c'est cohérent.

Je dis, utilisez tout ce que votre équipe veut pour votre projet. Mais si vous travaillez sur du code hérité ou que vous vous joignez à une équipe, respectez le style qui est présent pour plus de cohérence.

1
Rob Prouse

Je préfère également CamelCase, en effet, j'ai surtout vu des gens utiliser CamelCase en C++. Personnellement, je n'utilise aucun préfixe attendu pour les membres et interfaces privés/protégés:

class MyClass : public IMyInterface {
public:
    unsigned int PublicMember;
    MyClass() : PublicMember(1), _PrivateMember(0), _ProtectedMember(2) {}
    unsigned int PrivateMember() {
        return _PrivateMember * 1234; // some senseless calculation here
    }
protected:
    unsigned int _ProtectedMember;
private:
    unsigned int _PrivateMember;
};
// ...
MyClass My;
My.PublicMember = 12345678;

Pourquoi j'ai décidé d'omettre les préfixes pour les membres publics: Parce que les membres publics étaient accessibles directement comme dans les structures et ne heurtaient pas les noms privés. Au lieu d'utiliser des traits de soulignement, j'ai également vu des gens utiliser la première lettre minuscule pour les membres.

struct IMyInterface {
    virtual void MyVirtualMethod() = 0;
};

Les interfaces ne contiennent par définition que des méthodes virtuelles pures qui doivent être implémentées ultérieurement. Cependant, dans la plupart des situations, je préfère les cours abstraits, mais c'est une autre histoire.

struct IMyInterfaceAsAbstract abstract {
    virtual void MyVirtualMethod() = 0;
    virtual void MyImplementedMethod() {}
    unsigned int EvenAnPublicMember;
};

Voir Manuel de norme de codage C++ haute intégrité pour plus d'inspiration.

1
bkausbk

Mon équipe suit ceci convention de code Google C++ :

Voici un exemple de nom de variable:

string table_name;  // OK - uses underscore.
string tablename;   // OK - all lowercase.

string tableName;   // Bad - mixed case.
1
Tho

Si vous utilisez CamelCase, la convention consiste à mettre en majuscule la première lettre pour les structures de classes et les noms de type non primitifs, et à minuscule la première lettre pour les membres de données. La capitalisation des méthodes a tendance à être un sac mixte, mes méthodes ont tendance à être des verbes et sont déjà distinguées par des parens donc je ne capitalise pas les méthodes.

Personnellement, je n'aime pas lire le code CamelCase et je préfère souligner les minuscules pour les identificateurs de données et de méthodes, mettre en majuscule les types et réserver les majuscules pour les acronymes et le cas rare où j'utilise une macro (avertissement, c'est une MACRO).

0
Roger Nelson