Annexe 1 • Norme C++
Cette page contient les règles de norme que doivent respecter vos programmes en C++. Il s’agit majoritairement de règles dont l’impact est cosmétique, dont l’intérêt est de faciliter la lecture de votre code par vos camarades, vos enseignants et vous-même dans le futur.
Les exemples de code dans les vidéos et dans les sujets ne sont pas garantis d’être à la norme.
Les règles ajoutées sur cette page ne s’appliquent pas rétroactivement : vous ne pouvez pas être sanctionnés pour une règle qui n’y figure pas à date de rendu.
1. Règles générales
1.a. Structure d’un projet
Depuis la racine du projet :
Makefilesrc/- fichiers sources
.cpp - fichiers en-têtes
.hpp
- fichiers sources
Les fichiers en-têtes vivent dans le même dossier que les fichiers sources. Lors de la compilation passez -Isrc.
1.b. Indentation
Votre code doit être indenté de 4 espaces. Les tabulations sont interdites.
Les labels de classe (public, private, protected) et de switch (case, default) ne sont pas soumis à l’indentation obligatoire. Vous pouvez choisir de les indenter ou non.
Les namespaces ne sont pas soumis à l’indentation obligatoire lorsqu’ils sont dans un fichier qui ne définit rien dans l’étendue globale.
1.c. Lignes vides
Doivent être séparés d’une ligne vide les déclarations qui contiennent un corps entre accolades et les implémentations de fonctions.
class toto {
void tata()
{
// [...]
}
void toto()
{
// [...]
}
};
enum class foo {
// [...]
};
void tata()
{
// [...]
}
Les déclarations ne contenant pas accolades peuvent être groupée par genre.
class foo;
class bar;
void tata(foo &);
foo &toto();
enum riri;
enum fifi;
extern int g_patate;
1.d. Fins de lignes
Vos lignes doivent être terminées par des line feed (LF) et non pas par des carriage return + line feed (CRLF).
1.e. Noms de variables et de paramètres
Les noms des variables et des paramètres doivent être explicites. Des convention existent pour :
i,jetkpour nommer des compteurs ;npour nommer une quantité :- après laquelle s’arrêter, ou
- lue par un appel système.
Évitez les noms tels que a, b, a1, stuff, etc.
Il existe tout de même des exceptions en particulier lorsque vous faites des maths.
Soyez toujours prêts à justifier un nom de variable.
1.f. Types des pointeurs et des références
Le symbole de pointeur ou de référence doit être collé au nom auquel il s’applique et nom pas au type.
1.g. using namespace
Il est interdit d’utiliser la close using namespace sauf pour utiliser des littéraux.
Les closes using namespace, lorsqu’elles sont utilisée doivent lettre dans une fonction, sauf si c’est impossible.
1.h. Nombre maximum de colones
Votre code ne doit pas dépasser les 80 colones de largeur.
2. Opérateurs
2.a. Opérateurs binaires
Les opérateurs binaires doivent toujours être séparés de part et d’autre par un seul espace. Si une opération est trop longue pour tenir sur une seule ligne, faites un retour à la ligne avant l’opérateur et alignez la reprise sur la colonne où commence l’expression.
// OK
a = 12 * 4;
b = a + 6;
a != b
if (a != b
&& b != 2) {
// some code ...
}
// NOK
a = 12 *4;
b=a+6;
a!=b
if (a != b &&
b != 2) {
// some code ...
}
2.b. Opérateurs unaires
Les opérateurs unaire !, * et & ne doivent pas être séparés de leur opérande.
// OK
a = !b;
ptr = &a;
deref = *ptr;
// NOK
a = ! b;
ptr = & a;
deref = * ptr;
Les opérateurs pré et post incrément sont autorisés sur justification.
// OK
a += 1;
a = a + 1;
a -= 1:
// OK with justification
++a;
a++;
--a;
a--;
2.c. Opérateur de cast
3. Fonctions
3.a. Longueur
Les fonctions sont limitées à 25 lignes.
3.b. Appartenance à une classe
Toutes vos fonctions doivent être membres du classe sauf instruction contraire.
Ne sont pas concernées :
- la fonction
main; - les surcharges d’opérateur qui ne peuvent pas être membre (comme
operator<<) ; - les fonctions templates.
3.c. Names
Vos fonctions doivent porter des noms cohérents et explicites. Essayez d’utiliser des verbes.
En cas de conflit de nommage avec une fonction des bibliothèques, mettez votre fonction dans un namespace “stu”.
3.d. Accolades et parenthèses
Les accolades qui délimitent le corps d’une fonction doivent s’ouvrir et se fermer sur leur propre ligne.
Il doit n’y avoir aucun espace entre le nom d’une fonction et la parenthèse ouvrante de ses paramètres.
Il ne doit pas y avoir d’espace entre les parenthèses et les paramètres.
// OK
int main(void)
{
// function body
}
// NOK
int main(void) {
// function body
}
// NOK
int main ( void )
{
// function body
}
3.e. Paramètres
Une fonction ne doit pas prendre plus de 4 paramètres. Si vous pensez devoir en passer davantage tournez vous vers une classe ou une structure ou essayez de simplifier le travail de cette fonction.
Les fonctions qui ne prennent pas de paramètre doivent être signalées par void entre parenthèses.
Si les paramètres dépassent le nombre maximal de colones, ils peuvent être séparés par des retours à la ligne et alignés sur la parenthèse ouvrante.
// OK
s_foo very_long_function_name_with_parameters(int variable_1,
int variable_2,
int variable_3)
{
s_foo out;
out.f_a = 12;
out.f_b = 42;
return out;
}
3.f. Déclaration de variable
Les déclarations de variable peuvent être écrites à n’importe quel moment au sein d’une fonction.
3.g. Commentaires
Il doit n’y avoir aucun commentaire à l’intérieur d’une fonction. Le nom d’une fonction et son code doivent rendre son rôle clair. Vous pouvez écrire un commentaire en amont d’une fonction pour préciser son comportement.
/*
* adds params a and b
* returns the result
*/
int add(int a, int b)
{
return a + b;
}
3.h. Lignes vides
Pour simplifier la lecture de vos fonctions, vous avez le droit de séparer deux lignes de code non vides par une ligne de code vide.
4. Mots clé
4.a. Mots clés autorisés
4.b. Limitations avec les boucles
Vous êtes limités à une seule boucle imbriquée dans une autre. Si vous avez besoin de plus de boucle : faites une nouvelle fonction.
// OK
void foo(void)
{
while (/* [...] */) {
while (/* [...] */) {
// some code
}
}
}
// NOK
void bar(void)
{
while (/* [...] */) {
while (/* [...] */) {
while (/* [...] */) {
// some code
}
}
}
}
4.d. Parenthèses
Les parenthèses et les mots clés doivent être séparés d’un espace. Aucune exception.
Comme pour les fonctions, pas d’espacement entre les parenthèses et leur contenu.
// OK
if (true) {
// ...
}
char *str = malloc(sizeof (char) * 12);
// NOK
if( true ){
// ...
}
4.e. Accolades
Les accolades des tests doivent s’ouvrir sur la ligne du mot clé (et/ou de la condition). Lorsqu’il y a un else, il doit s’écrire sur la même ligne que l’accolade fermante le précédent. Le else doit être séparé d’un espace de l’accolade qui le précède et de l’accolade qui le suit.
// OK
if (a == b) {
// code
} else {
// code
}
// NOK
if (a == b)
{
// code
}
else
{
// code
}
if (a == b){
// code
}
5. Pré-processeur
5.a. Fichiers en-tête
Doivent avoir l’extension .hpp et doivent être protégés contre la double inclusion :
#ifndef FILENAME_HPP_
#define FILENAME_HPP_
// your header's content
#endif /* FILENAME_HPP_ */
The name of the ifndef and define shall be constructed as such:
filename.hpp->FILENAME_HPP_tata.hpp->TATA_HPP_
5.b. Inclusion
L’inclusion d’en-tête système doit se faire avant l’inclusion des vôtres.
Les inclusions système se font avec des chevrons et les inclusions locales se font avec des guillements.