1. C++
Quelques habitudes à prendre
-
Le nom du fichier doit refléter sa fonctionnalité, choisissez des noms cohérents
fonctions
,fichier
,tp1
, … ne donnent aucune indication sur le contenu ! -
Une fonction = Une fonctionnalité. Autrement dit, une fonction ne doit faire que ce que l’on attend d’elle (KISS : Keep It Simple, Stupid).
Par exemple, une fonction dont le but est de créer et renvoyer un tableau ne doit pas afficher quelque chose ni modifier une variable ! Elle doit juste créer et renvoyer un tableau. Sauf cas pathologique, quand vous commandez un café vous ne souhaitez pas que le serveur y ajoute une sardine dedans, même avec le sourire.
-
Les fonctions et variables doivent avoir des noms compréhensibles et surtout en rapport avec leurs fonctions !
int truc = 2
n’est pas très parlant -
À chaque nouvelle fonctionnalité, suivez la procédure suivante :
-
Compilation : tant qu’elle plante, on corrige1, sinon…
-
… Validation ! Tant que le résultat n’est pas bon, on corrige, sinon…
-
… Passer à la suite
Concernant les classes
Nom des paramètres
Une class
en C++
dispose (souvent) de paramètres privés (private
) ou publiques (public
). Le choix du nom de ces variables n’est pas sans incidence. Nous vous conseillons de terminer le nom de ces variables par un “underscore” _
. Cela permet d’éviter toute confusion avec d’autres variables, par exemple :
class MaClasse{
private:
int N_;
public:
MaClasse(int N){ N_ = N;}
};
Sans le underscore , nous pourrions confondre l’arguement N
(extérieure) avec la variable privée de la classe.
Méthode const
Une méthode est une fonction membre d’une classe. Si le prototype d’une méthode se termine par const
cela signifie (au compilateur) que la méthode n’altère pas les paramètres de l’instance de la classe. Prenez l’habitude de placez des const
quand il faut dès le début, sinon vous allez au delà de grands changements…
class MaClasse{
private:
int N_;
public:
MaClasse(int N){N_ = N;}
// Méthode "constante" :
void Print() const{std::cout << "N = " << N_;}
// Méthode non "constante" modifiant le paramètre N_
void Set(int N) {N_ = N;}
};
Où trouver de l’aide et des informations pertinentes ?
Google (ou autre) sera votre bras droit dans la recherche d’information sur le C++
. Citons tout de même les sites suivants qui sont des valeurs sûres :
- Pour la syntaxe : cppreference.com ou cplusplus.com
- Pour des questions pointues : Stack Overflow
- L’excellente FAQ de isocpp présentant des exemples de cas pathologiques
Tutoriels en ligne
Ces derniers ne manquent pas, tels que :
Les erreurs classiques
Avant de nous appeler et au risque de patienter longuement avant notre venue : Google est votre ami (encore et pour une fois). Mais en général, l’erreur est classique…
Erreur de compilateur
Le compilateur renvoie un message d’erreur ? Stop. On arrête tout : on doit débugguer. On ne continue surtout pas son code au risque de rendre l’erreur encore plus incompréhensible.
- Regardez le premier message d’erreur, celui le plus en haut (d’autres erreurs découlent probablement de l’erreur primaire) double operator() (int i) const; // Accès à la valeur (recopie)
- Essayez de lire et de comprendr double operator() (int i) const; // Accès à la valeur (recopie)que dit votre compilateur. Au début, on galère, après on y arrive (un peu).
Quelques erreurs classiques :
- Oublie d’un point virgule à double operator() (int i) const; // Accès à la valeur (recopie)in d’une commande
- Oublie de typer une variabl double operator() (int i) const; // Accès à la valeur (recopie)une fonction
- Oublie de déclarer la fonct double operator() (int i) const; // Accès à la valeur (recopie)t/ou d’inclure le fichier d’en-tête contenant la dite fonction
- Erreur de typographie :
sdt::vector
au lieu destd::vector
Certains warning
méritent aussi de s’y attarder.
Erreur au lancement
La compilation se passe bien, le programme se lance mais ne donne pas le résultat voulu et/ou plante. Stop. On arrête tout. On débugue.
L’utilisation d’un débugueur (un vrai) est conseillé, comme gdb (notez qu’il y en a un dans VSCode). Nous utiliserons cependant la mauvaise habitude de débuguer à coup de cout << "coucou"
pour vérifier si le programme plante avant ou après une commande. Le but est de localiser l’erreur, ensuite en général, ça saute aux yeux.
- Segmentation Fault : la pire erreur à débuguer. C’est un problème de mémoire: votre programme cherche à lire ou à écrire sur un emplacement mémoire pour lequel il n’a pas le droit de le faire. Pour les débusquer, c’est délicat car le programme peut fonctionner une fois, et pas la fois suivante. Le débuguage à cout de
cout
est parfois mis à mal. En général il faut : - Surveillez l’utilisation que vous avez des pointeurs/références
- Surveillez les sorties de vos fonctions : retournez vous une variable qui est, en fait, détruite ?
- Le résultat est faux : bon courage, il faut mettre les mains dans le cambouis ! Car non, l’erreur ne vient pas de l’ordinateur, mais bien de votre code.
Quelques mauvaises habitudes
- Évitez le plus possible
using namespace std
: voir ici et surtout à prohiber dans les fichiers header ! - Passage d’argument par recopie : en C++, les arguments sont par défaut passés par copie*. Rendre **constant un argument passé par copie est alors inutile**. Nous banirons donc ce genre de pratique :
... fonction(const Type T){...}
- Passage d’argument par référence : cette pratique permet d’envoyer non pas la valeur mais l’adresse de la variable à la fonction :
... fonction(const Type &T){...}
- Cette méthode est très intéressante quand
Type
n’est pas élémentaire (double
,float
,int
, …) et nécessite une taille mémoire importante (tableaux (std::vector
) ou matrice par exemple) :
... fonction(const std::vector<double> & v, ...){...}
- Pour des entités élémentaires, c’est à la fois inutile et potentiellement dangereux. D’autre part, l’optimisation effectuée par le compilateur perd en efficacité avec de tels arguments. Ainsi, les prototypes de ce type seront persona non grata :
... fonction(const double & d, const int & a, ...){...}
Quelques liens utiles
friend operator<<
ouoperator<<
?operator
: méthode ou fonction ?const int &
en argument de fonction ?
-
Vous apprendrez vite à comprendre ce que vous dit le compilateur ↩︎