summaryrefslogtreecommitdiffhomepage
path: root/fr-fr/c++-fr.html.markdown
diff options
context:
space:
mode:
authorDmitrii Kuznetsov <torgeek@users.noreply.github.com>2021-02-22 18:36:35 +0300
committerGitHub <noreply@github.com>2021-02-22 18:36:35 +0300
commitbc8bd2646f068cfb402850f7c0f9b1dbfe81e5a0 (patch)
tree89213fd6afbf9cc9303c1c2fa08dafc840a9d99d /fr-fr/c++-fr.html.markdown
parent363d5281f1e3d5bee6339b5316405b0a4b592c49 (diff)
parent110511a10110f96b20f107c078f7d5ef4c01b109 (diff)
Merge pull request #1 from adambard/master
Merge from original adambard
Diffstat (limited to 'fr-fr/c++-fr.html.markdown')
-rw-r--r--fr-fr/c++-fr.html.markdown915
1 files changed, 915 insertions, 0 deletions
diff --git a/fr-fr/c++-fr.html.markdown b/fr-fr/c++-fr.html.markdown
new file mode 100644
index 00000000..c8603756
--- /dev/null
+++ b/fr-fr/c++-fr.html.markdown
@@ -0,0 +1,915 @@
+---
+language: c++
+filename: learncpp-fr.cpp
+contributors:
+ - ["Steven Basart", "http://github.com/xksteven"]
+ - ["Matt Kline", "https://github.com/mrkline"]
+ - ["Geoff Liu", "http://geoffliu.me"]
+ - ["Connor Waters", "http://github.com/connorwaters"]
+translators:
+ - ["Xuan-thi Nguyen", "http://github.com/mellenguyen"]
+lang: fr-fr
+---
+
+C++ est un langage de programmation système qui,
+[selon son créateur Bjarne Stroustrup](http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2014/Keynote),
+fut créé pour
+
+- être un "C amélioré"
+- gérer l'abstraction des données
+- gérer la programmation orienté objet
+- gérer la programmation générique
+
+Bien que sa syntaxe puisse être plus difficile ou complexe que des langages
+récents, il est largement utilisé car il compile en instructions natives qui
+peuvent être directement exécutées par le processeur et offre un contrôle
+rigoureux du matériel (comme le C) tout en fournissant des caractéristiques de
+haut niveau telles que la généricité, les exceptions et les classes.
+Cette combinaison de vitesse et de fonctionnalités rend le C++ un des langages
+de programmation les plus utilisés au monde.
+
+```c++
+/////////////////////////////////
+// Comparaison avec le C
+/////////////////////////////////
+
+// C++ est _presque_ un sur-ensemble du C et partage sa syntaxe basique pour les
+// déclarations de variables, les types primitifs et les fonctions.
+
+// Tout comme en C, le point d'entrée de votre programme est une fonction
+// appelée main, avec un integer comme type de retour.
+// Cette valeur constitue l'état de fin d'exécution du programme.
+// Voir http://en.wikipedia.org/wiki/Exit_status pour plus d'informations.
+int main(int argc, char** argv)
+{
+ // Les arguments de ligne de commande sont passés avec argc et argv de la
+ // même manière qu'en C.
+ // argc indique le nombre d'arguments,
+ // et argv est un tableau de chaînes façon C (char*)
+ // représentant les arguments.
+ // Le premier argument est le nom par lequel le programme est appelé.
+ // argc et argv peuvent être omis si vous ne vous souciez pas des
+ // arguments, nous donnant comme signature de fonction int main()
+
+ // Un état de fin d'exécution 0 indique le succès.
+ return 0;
+}
+
+// Cependant, C++ varie du C selon certains éléments:
+
+// En C++, les caractères littéraux sont des chars
+sizeof('c') == sizeof(char) == 1
+
+// En C, les caractères littéraux sont des ints
+sizeof('c') == sizeof(int)
+
+// C++ a un prototypage strict
+void func(); // fonction qui ne prend aucun argument
+
+// En C
+void func(); // fonction qui peut prendre n'importe quel nombre d'arguments
+
+// Utilise nullptr au lieu de NULL en C++
+int* ip = nullptr;
+
+// Les en-têtes standards du C sont disponibles en C++,
+// mais sont préfixés avec "c" et n'ont pas de suffixe .h
+#include <cstdio>
+
+int main()
+{
+ printf("Bonjour tout le monde!\n");
+ return 0;
+}
+
+/////////////////////////////////
+// Surchage de fonctions
+/////////////////////////////////
+
+// C++ gère la surchage de fonctions
+// Chaque fonction fournie prend différents paramètres.
+
+void print(char const* maChaine)
+{
+ printf("Chaîne %s\n", maChaine);
+}
+
+void print(int monEntier)
+{
+ printf("Mon entier est %d", monEntier);
+}
+
+int main()
+{
+ print("Bonjour"); // Utilise void print(const char*)
+ print(15); // Utilise void print(int)
+}
+
+/////////////////////////////////////////////
+// Arguments par défaut de fonctions
+/////////////////////////////////////////////
+
+// Vous pouvez fournir des arguments par défaut pour une fonction s'ils ne sont
+// pas fournis par l'appelant.
+
+void faitDesChosesAvecDesEntiers(int a = 1, int b = 4)
+{
+ // Do something with the ints here
+}
+
+int main()
+{
+ faitDesChosesAvecDesEntiers(); // a = 1, b = 4
+ faitDesChosesAvecDesEntiers(20); // a = 20, b = 4
+ faitDesChosesAvecDesEntiers(20, 5); // a = 20, b = 5
+}
+
+// Les arguments par défaut doivent être à la fin de la liste des arguments.
+
+void invalidDeclaration(int a = 1, int b) // Erreur !
+{
+}
+
+
+//////////////////////////
+// Espaces de nom
+//////////////////////////
+
+// Les espaces de nom fournissent une séparation des portées pour les
+// variables, fonctions, et autres déclarations.
+// Les espaces de nom peuvent être imbriqués.
+
+namespace Premier {
+ namespace Imbrique {
+ void foo()
+ {
+ printf("Ceci est le Premier::Imbrique::foo\n");
+ }
+ } // fin de l'espace de nom Imbrique
+} // fin de l'espace de nom Premier
+
+namespace Second {
+ void foo()
+ {
+ printf("Ceci est le Second::foo\n")
+ }
+}
+
+void foo()
+{
+ printf("Ceci est un foo global\n");
+}
+
+int main()
+{
+ // Inclut tous les symboles de l'espace de nom Second dans la portée
+ // actuelle. Notez que le foo() simple ne marche plus, car l'appel est
+ // ambigu entre le foo de l'espace de nom Second et celui de premier
+ // niveau.
+ using namespace Second;
+
+ Second::foo(); // imprime "Ceci est le Second::foo"
+ Premier::Imbrique::foo(); // imprime "Ceci est le Premier::Imbrique::foo"
+ ::foo(); // imprime "Ceci est un foo global"
+}
+
+/////////////////////////
+// Entrée/Sortie
+/////////////////////////
+
+// Les entrées et sorties en C++ utilisent des flux (streams)
+// cin, cout et cerr représentent stdin, stdout et stderr.
+// << est l'opérateur d'insertion et >> est l'opérateur d'extraction.
+
+#include <iostream> // Inclusion pour les flux d'entrée/sortie
+
+// Les flux sont dans l'espace de nom std (librairie standard)
+using namespace std;
+
+int main()
+{
+ int monEntier;
+
+ // Affiche sur stdout (ou le terminal/l'écran)
+ cout << "Entrez votre chiffre favori:\n";
+ // Prend l'entrée clavier
+ cin >> monEntier;
+
+ // cout peut également être formaté
+ cout << "Votre chiffre favori est " << monEntier << "\n";
+ // imprime "Votre chiffre favori est <monEntier>"
+
+ cerr << "Utilisé pour les messages d'erreurs";
+}
+
+/////////////////////////////////
+// Chaînes de caractères
+/////////////////////////////////
+
+// Les chaînes de caractères en C++ sont des objets et ont plusieurs fonctions
+// membres
+#include <string>
+
+// Les chaînes de caractères sont aussi dans l'espace de
+// nom std (librairie standard)
+using namespace std;
+
+string maChaine = "Bonjour";
+string monAutreChaine = " tout le monde !";
+
+// + est utilisé pour la concaténation.
+cout << maChaine + monAutreChaine; // Bonjour tout le monde !"
+
+cout << maChaine + " toi !"; // "Bonjour toi !"
+
+// Les chaînes de caractères C++ sont mutables.
+maChaine.append(" le chien !");
+cout << maChaine; // "Bonjour le chien !"
+
+
+//////////////////////
+// Références
+//////////////////////
+
+// En plus des pointeurs comme ceux en C,
+// C++ possède des _références_.
+// Ce sont des types de pointeurs qui ne peuvent pas être réassignés
+// une fois initialisés, et ne peuvent pas être nulles.
+// Ils partagent la même syntaxe que les variables elles-mêmes:
+// les * ne sont pas nécessaires pour les déréférencer et
+// & (addresse de) n'est pas utilisé pour l'assignement.
+
+using namespace std;
+
+string foo = "Je suis foo";
+string bar = "Je suis bar";
+
+
+string& fooRef = foo; // Ceci créé une référence à foo
+fooRef += ". Salut!"; // Modifie foo à travers la référence
+cout << fooRef; // Affiche "Je suis foo. Salut!"
+
+// Ne réassigne pas "fooRef". Ceci revient à faire "foo = bar", et
+// foo == "I am bar"
+// après cette ligne.
+cout << &fooRef << endl; // Affiche l'adresse de foo
+fooRef = bar;
+cout << &fooRef << endl; // Affiche toujours l'adresse de foo
+cout << fooRef; // Affiche "Je suis bar"
+
+// L'adresse de fooRef reste la même, c.-à-d. référence toujours foo.
+
+
+const string& barRef = bar; // Créé une référence constante de bar.
+// Comme en C, les valeurs constantes (et pointeurs et références) ne peuvent
+// être modifiées.
+
+// Erreur, les valeurs constantes ne peuvent être modifiées.
+barRef += ". Salut!";
+
+// Parenthèse: avant de développer le sujet des références, nous devons
+// introduire un concept appelé un objet temporaire. Supposons que nous ayons
+// le code suivant :
+string objetTemporaireFun() { ... }
+string valeurRetenu = objetTemporaireFun();
+
+// Les différents événements se déroulant à la seconde ligne sont :
+// - un objet chaîne de caractères est retourné de objetTemporaireFun
+// - une nouvelle chaîne de caractères est construite avec la valeur
+// retournée comme argument du constructeur
+// - l'objet retourné est détruit.
+// L'objet retourné est appelé un objet temporaire. Les objets temporaires sont
+// créés chaque fois qu'une fonction retourne un objet, et sont détruits à la
+// fin de l'évaluation de l'expression fermante (c'est ce que le standard
+// énonce, mais les compilateurs sont autorisés à changer ce comportement.
+// Cherchez "optimisation valeur de retour" si vous êtes intéressé par ce genre
+// de détails).
+// Dans cette ligne de code :
+foo(bar(objetTemporaireFun()))
+
+// en supposant que foo et bar existent, l'objet retourné de objetTemporaireFun
+// est passé à bar, et est détruit avant que foo soit appelé.
+
+// Revenons maintenant aux références. L'exception à la règle "objet détruit à
+// la fin de l'expression fermante" s'applique dans le cas d'un objet
+// temporaire lié à une référence constante, où sa durée de vie se voit
+// prolongée à la portée courante :
+
+void referenceConstanteObjetTemporaireFun() {
+ // referenceConst prend l'objet temporaire, et est valide jusqu'à la fin de
+ // la fonction.
+ const string& referenceConst = objetTemporaireFun();
+ ...
+}
+
+// Un autre type de référence introduit en C++11 est spécifiquement pour les
+// objets temporaires. Vous ne pouvez pas avoir de variable de ce type, mais
+// il prime dans la résolution de surcharge :
+
+void fonctionFun(string& s) { ... } // Référence régulière
+void fonctionFun(string&& s) { ... } // Référence un objet temporaire
+
+string foo;
+// Appelle la version avec référence régulière
+fonctionFun(foo);
+
+// Appelle la version avec référence temporaire
+fonctionFun(objetTemporaireFun());
+
+// Par exemple, vous aurez ces deux versions de constructeurs pour
+// std::basic_string :
+basic_string(const basic_string& other);
+basic_string(basic_string&& other);
+
+// L'idéal étant de construire une nouvelle chaîne de caractères avec un objet
+// temporaire (qui sera détruit de toute façon), nous pouvons ainsi avoir un
+// constructeur qui "sauve" des parties de cette chaîne de caractères
+// temporaire. Vous verrez ce concept sous le nom de "sémantique de mouvement".
+
+////////////////////////
+// Enumérations
+////////////////////////
+
+// Les énumérations sont un moyen d'assigner une valeur à une constante
+// fréquemment utilisée pour une meilleure visualisation et lecture du code.
+enum ETypesDeVoitures
+{
+ Berline,
+ Hayon,
+ 4x4,
+ Break
+};
+
+ETypesDeVoitures ObtenirVoiturePreferee()
+{
+ return ETypesDeVoitures::Hayon;
+}
+
+// En C++11, il existe une manière simple d'assigner un type à une énumération,
+// ce qui peut-être utile en sérialisation de données et conversion
+// d'énumérations entre le type voulu et ses constantes respectives.
+enum ETypesDeVoitures : uint8_t
+{
+ Berline, // 0
+ Hayon, // 1
+ 4x4 = 254, // 254
+ Hybride // 255
+};
+
+void EcrireOctetDansLeFichier(uint8_t ValeurEntree)
+{
+ // Sérialise la valeur d'entrée dans un fichier
+}
+
+void EcrireTypeVoiturePrefereDansLeFichier(ETypesDeVoitures TypeVoitureEntree)
+{
+ // L'énumération est implicitement convertie en uint8_t du à la déclaration
+ // de son type d'énumération
+ EcrireOctetDansLeFichier(TypeVoitureEntree);
+}
+
+// D'autre part, vous pourriez ne pas vouloir que des énumérations soient
+// accidentellement converties en entiers ou en d'autres énumérations. Il est
+// donc possible de créer une classe d'énumération qui ne sera pas
+// implicitement convertie.
+enum class ETypesDeVoitures : uint8_t
+{
+ Berline, // 0
+ Hayon, // 1
+ 4x4 = 254, // 254
+ Hybride // 255
+};
+
+void EcrireOctetDansLeFichier(uint8_t ValeurEntree)
+{
+ // Sérialise la valeur d'entrée dans un fichier
+}
+
+void EcrireTypeVoiturePrefereDansLeFichier(ETypesDeVoitures TypeVoitureEntree)
+{
+ // Ne compilera pas même si ETypesDeVoitures est un uint8_t car
+ // l'énumération est déclarée en tant que "classe d'énumération" !
+ EcrireOctetDansLeFichier(TypeVoitureEntree);
+}
+
+///////////////////////////////////////////////////
+// Classes et programmation orientée objet
+///////////////////////////////////////////////////
+
+#include <iostream>
+
+// Déclare une classe.
+// Les classes sont habituellement déclarées dans les fichiers d'en-tête (.h ou .hpp).
+class Chien {
+ // Les variables et fonctions membres sont privées par défaut.
+ std::string nom;
+ int poids;
+
+// Tous les membres suivants sont publiques jusqu'à ce que "private:" ou
+// "protected:" soit trouvé
+public:
+
+ // Constructeur par défaut
+ Chien();
+
+ // Déclaractions de fonctions membres (implémentations à suivre)
+ // Notez que nous utilisons std::string ici au lieu de placer
+ // using namespace std;
+ // au-dessus.
+ // Ne jamais utiliser une instruction "using namespace" dans l'en-tête.
+ void initialiserNom(const std::string& nomDuChien);
+
+ void initialiserPoids(int poidsDuChien);
+
+ // Les fonctions qui ne modifient pas l'état de l'objet devraient être
+ // marquées en constantes avec const.
+ // Ceci vous permet de les appeler avec une référence constante vers l'objet.
+ // Notez aussi que les fonctions devant être surchargées dans des classes
+ // dérivées doivent être explicitement déclarées avec _virtual_.
+ // Les fonctions ne sont pas virtuelles par défault pour des raisons de
+ // performances.
+ virtual void imprimer() const;
+
+ // Les fonctions peuvent également être définies à l'intérieur du corps de
+ // la classe. Ces fonctions sont automatiquement "inline".
+ void aboyer() const { std::cout << nom << " fait ouaf !\n"; }
+
+ // En plus des constructeurs, C++ fournit des destructeurs.
+ // Ils sont appelés quand l'objet est supprimé ou dépasse le cadre de sa
+ // portée. Ceci permet de puissants paradigmes tels que RAII
+ // (voir plus loin)
+ // Le destructeur devrait être virtuel si la classe est abstraite;
+ // s'il n'est pas virtuel, alors le destructeur de la classe dérivée ne
+ // sera pas appelé si l'objet est détruit par le biais d'une référence à la
+ // classe de base ou d'un pointeur.
+ virtual ~Chien();
+
+}; // Un point virgule doit clôre la définition de la classe.
+
+// Les fonctions membres de la classe sont habituellement implémentées dans des
+// fichiers .cpp.
+Chien::Chien()
+{
+ std::cout << "Un chien a été construit\n";
+}
+
+// Les objets (comme les chaînes de caractères) devraient être passés par
+// référence si vous les modifiez ou par référence constante si vous ne les
+// modifiez pas.
+void Chien::initialiserNom(const std::string& nomDuChien)
+{
+ nom = nomDuChien;
+}
+
+void Chien::initialiserPoids(int poidsDuChien)
+{
+ poids = poidsDuChien;
+}
+
+// Notez que le mot-clé "virtual" est nécessaire uniquement à la déclaration,
+// et non à la définition.
+void Chien::imprimer() const
+{
+ std::cout << "Le chien s'appelle " << nom << " et pèse " << poids << "kg\n";
+}
+
+Chien::~Chien()
+{
+ cout << "Au revoir " << nom << " !\n";
+}
+
+int main() {
+ Chien monChien; // imprime "Un chien a été construit"
+ monChien.initialiserNom("Barkley");
+ monChien.initialiserPoids(10);
+ monChien.imprime(); // imprime "Le chien s'appelle Barkley et pèse 10 kg"
+ return 0;
+} // prints "Au revoir Barkley !"
+
+// Héritage :
+
+// Cette classe hérite de toutes les propriétés publiques et protégées de la
+// classe Chien ainsi que celles privées, mais n'ont pas accès direct aux
+// membres et méthodes privés sans l'aide d'une méthode publique ou protégée
+class ChienDomestique : public ChienDomestique {
+
+ void definirProprietaire(const std::string& proprietaireDuChien);
+
+ // Surcharge le comportement de la fonction d'impression pour tous les
+ // ChienDomestiques.
+ // Voir https://fr.wikipedia.org/wiki/Polymorphisme_(informatique)#Polymorphisme_par_sous-typage
+ // pour une introduction plus générale si vous n'êtes pas familier avec le
+ // concept de polymorphisme par sous-typage (appelé aussi polymorphisme
+ // d'inclusion).
+ // Le mot-clé "override" est optionnel mais assure que vous surchargez bien
+ // la méthode de la classe de base.
+ void imprimer() const override;
+
+private:
+ std::string proprietaire;
+};
+
+// Pendant ce temps, dans le fichier .cpp correspondant :
+
+void ChienDomestique::definirProprietaire(const std::string& proprietaireDuChien)
+{
+ proprietaire = proprietaireDuChien;
+}
+
+void ChienDomestique::imprimer() const
+{
+ // Appelle la fonction "imprimer" dans la classe de base Chien
+ Chien::imprimer();
+ std::cout << "Le chien appartient à " << proprietaire << "\n";
+ // Affiche "Le chien est <nom> et pèse <poids>"
+ // "Le chien appartient à <proprietaire>"
+}
+
+////////////////////////////////////////////////////
+// Initialisation et opérateur de surcharge
+////////////////////////////////////////////////////
+
+// En C++, vous pouvez surcharger le comportement d'opérateurs tels
+// que +, -, *, /, etc.
+// La surcharge se fait en définissant une fonction qui sera appelée à chaque
+// fois que l'opérateur sera utilisé.
+
+#include <iostream>
+using namespace std;
+
+class Point {
+public:
+ // Les variables membres peuvent avoir des valeurs par défaut
+ double x = 0;
+ double y = 0;
+
+ // Définit un constructeur par défaut qui ne fait rien
+ // mais initialise le Point à la valeur par défaut (0, 0)
+ Point() { };
+
+ // La syntaxe suivante s'appelle une liste d'initialisation et est
+ // la façon correcte d'initialiser les valeurs des membres d'une classe.
+ Point (double a, double b) :
+ x(a),
+ y(b)
+ { /* Ne fait rien à part initialiser les valeurs */ }
+
+ // Surcharge l'opérateur +
+ Point operator+(const Point& rhs) const;
+
+ // Surcharge l'opérateur +=
+ Point& operator+=(const Point& rhs);
+
+ // Il serait également logique d'ajouter les opérateurs - et -=,
+ // mais nous les éclipsons par soucis de concision.
+};
+
+Point Point::operator+(const Point& rhs) const
+{
+ // Créé un nouveau point qui est la somme de celui-ci de rhs.
+ return Point(x + rhs.x, y + rhs.y);
+}
+
+Point& Point::operator+=(const Point& rhs)
+{
+ x += rhs.x;
+ y += rhs.y;
+ return *this;
+}
+
+int main () {
+ Point haut (0,1);
+ Point droite (1,0);
+ // Appelle l'opérateur + du Point
+ // Le point "haut" appelle la fonction + avec "droite" comme paramètre
+ Point resultat = haut + droite;
+ // Affiche "Le résultat est haut-droite (1,1)"
+ cout << "Le résultat est haut-droite (" << resultat.x << ','
+ << resultat.y << ")\n";
+ return 0;
+}
+
+////////////////////////////////
+// Patrons (templates)
+////////////////////////////////
+
+// Les templates (patrons) en C++ sont majoritairement
+// utilisés pour la programmation générique, bien qu'ils soient bien plus
+// puissants que les constructeurs génériques dans d'autres langages.
+// Ils gèrent également la spécialisation explicite et partielle ainsi que
+// les classes fonctionnelles; en fait, ils sont un langage fonctionnelles
+// Turing-complete embedded in C++ !
+
+// Nous commencons avec le genre de programmation générique auquel vous êtes
+// peut-être familier. Pour définir une classe ou fonction qui prend un type de
+// paramètre particulier :
+template<class T>
+class Boite {
+public:
+ // Dans cette classe, T représente n'importe quel type possible.
+ void inserer(const T&) { ... }
+};
+
+// Pendant la compilation, le compilateur génère des copies de chaque template
+// avec les paramètres substitués; ainsi, la définition complète de chaque
+// classe doit être présente à chaque appel. C'est pourquoi vous verrez les
+// classes de templates définies entièrement dans les fichiers d'en-tête.
+
+// Pour instancier une classe de template sur la pile ("stack") :
+Boite<int> boiteDEntiers;
+
+// et vous pouvez l'utiliser comme prévu :
+boiteDEntiers.inserer(123);
+
+// Vous pouvez, bien sûr, imbriquer les templates :
+Boite<Boite<int> > boiteDeBoites;
+boiteDeBoites.inserer(boiteDEntiers);
+
+// Jusqu'à C++11, il était nécessaire de placer un espace entre les deux '>'s,
+// sinon '>>' était parsé en tant qu'opérateur de décalage vers la droite.
+
+// Vous croiserez peut-être cette syntaxe
+// template<typename T>
+// à la place. Les mot-clé 'class' et 'typename' sont _généralement_
+// interchangeables. Pour plus d'explications, allez à
+// http://en.wikipedia.org/wiki/Typename
+// ou
+// https://fr.wikibooks.org/wiki/Programmation_C-C%2B%2B/Les_templates/Mot-cl%C3%A9_typename
+// (oui, ce mot-clé a sa propre page Wikipedia).
+
+// De manière similaire, un patron de fonction :
+template<class T>
+void aboyerTroisFois(const T& entree)
+{
+ entree.aboyer();
+ entree.aboyer();
+ entree.aboyer();
+}
+
+// Remarquez ici que rien n'est spécifié à propos du type du paramètre. Le
+// compilateur va générer et vérifier le type à chaque appel du patron, c'est
+// pourquoi l'appel de fonction suivant marche pour n'importe quel type 'T' qui
+// a une méthode constante 'aboyer' !
+
+Chien docile;
+docile.initialiserNom("Docile")
+aboyerTroisFois(docile); // Affiche "Docile fait ouaf !" trois fois.
+
+// Les paramètres génériques (ou paramètres template) ne sont pas forcément des
+// classes :
+template<int Y>
+void imprimerMessage() {
+ cout << "Apprenez le C++ en " << Y << " minutes !" << endl;
+}
+
+// Vous pouvez explicitement spécialiser les templates pour un code plus
+// optimisé. Bien sûr, les utilisations effectives de la spécialisation ne sont
+// pas aussi triviales que celle-ci.
+// Notez que vous avez toujours besoin de déclarer la fonction (ou classe)
+// comme template, même si vous spécifiez explicitement tous les paramètres.
+template<>
+void imprimerMessage<10>() {
+ cout << "Apprenez le C++ plus vite en seulement 10 minutes !" << endl;
+}
+
+// Affiche "Apprenez le C++ en 20 minutes !"
+imprimerMessage<20>();
+// Affiche "Apprenez le C++ plus vite en seulement 10 minutes !"
+imprimerMessage<10>();
+
+//////////////////////////////////
+// Gestion des exceptions
+//////////////////////////////////
+
+// La bibliothèque standard fournit quelques types d'exception
+// (voir http://en.cppreference.com/w/cpp/error/exception)
+// mais n'importe quel type peut être lancé en tant qu'exception.
+#include <exception>
+#include <stdexcept>
+
+// Toutes les exceptions lancées à l'intérieur d'un block _try_ peuvent être
+// attrapées par les blocs de traitement d'erreurs (_catch_ handlers).
+try {
+ // N'allouez pas des exceptions sur le tas (heap) en utilisant _new_.
+ throw std::runtime_error("Un problème s'est produit");
+}
+
+// Attrapez les exceptions avec des références constantes si ce sont des objets
+catch (const std::exception& ex)
+{
+ std::cout << ex.what();
+}
+
+// Attrape n'importe quelle exception non attrapée par les blocs _catch_
+// précédents
+catch (...)
+{
+ std::cout << "Exception inconnue attrapée";
+ throw; // Re-lance l'exception
+}
+
+////////////////
+// RAII
+////////////////
+
+// RAII signifie "Resource Acquisition Is Initialization", soit l'Acquisition
+// d'une Ressource est une Initialisation en français.
+// Il est souvent considéré comme le paradigme le plus puissant en C++ et
+// est le concept simple qu'un constructeur d'un objet acquiert les ressources
+// d'un objet et que le destructeur les libère.
+
+// Afin de comprendre son utilité, considérons une fonction qui utilise la
+// gestion d'un fichier C :
+void faireQuelqueChoseAvecUnFichier(const char* nomDuFichier)
+{
+ // Pour commencer, supposons que rien ne peut échouer.
+
+ FILE* fh = fopen(nomDuFichier, "r"); // Ouvre le fichier en lecture
+
+ faireQuelqueChoseAvecLeFichier(fh);
+ faireAutreChoseAvec(fh);
+
+ fclose(fh); // Ferme la gestion du fichier.
+}
+
+// Malheureusement, les choses deviennent compliquées avec la gestion
+// d'erreurs. Supposons que fopen échoue, et que faireQuelqueChoseAvecLeFichier
+// et faireAutreChoseAvec retournent des codes d'erreur si elles échouent.
+// (Les exceptions sont le meilleur moyen de gérer l'échec, mais des
+// programmeurs, surtout avec un passif en C,
+// sont en désaccord avec l'utilité des exceptions).
+// Nous devons maintenant vérifier chaque appel en cas d'échec et fermer la
+// gestion du fichier si un problème se produit.
+bool faireQuelqueChoseAvecUnFichier(const char* nomDuFichier)
+{
+ FILE* fh = fopen(nomDuFichier, "r"); // Ouvre le fichier en mode lecture.
+ if (fh == nullptr) // Le pointeur retourné est null à un échec.
+ return false; // Signale cet échec à l'appelant.
+
+ // Suppose que chaque fonction retourne faux si elle échoue
+ if (!faireQuelqueChoseAvecLeFichier(fh)) {
+        fclose(fh); // Ferme le flux d'entrée du fichier pour empêcher les fuites
+        return false; // Propage l'erreur
+ }
+ if (!faireAutreChoseAvec(fh)) {
+ fclose(fh);
+ return false;
+ }
+
+ fclose(fh);
+ return true;
+}
+
+// Les programmeurs en C clarifient souvent tout cela en utilisant goto :
+bool faireQuelqueChoseAvecUnFichier(const char* nomDuFichier)
+{
+ FILE* fh = fopen(nomDuFichier, "r");
+ if (fh == nullptr)
+ return false;
+
+ if (!faireQuelqueChoseAvecLeFichier(fh))
+ goto echec;
+
+ if (!faireAutreChoseAvec(fh))
+ goto echec;
+
+ fclose(fh); // Ferme la gestion du fichier
+ return true; // Indique le succès
+
+echec:
+ fclose(fh);
+ return false; // Propage l'erreur
+}
+
+// Si les fonctions indiquent des erreurs en utilisant des exceptions,
+// les choses sont un peu plus claires, mais toujours sous-optimales.
+void faireQuelqueChoseAvecUnFichier(const char* nomDuFichier)
+{
+ FILE* fh = fopen(nomDuFichier, "r"); // Ouvre le fichier en lecture
+ if (fh == nullptr)
+ throw std::runtime_error("Ouverture du fichier impossible.");
+
+ try {
+ faireQuelqueChoseAvecLeFichier(fh);
+ faireAutreChoseAvec(fh);
+ }
+ catch (...) {
+ // Assurez-vous de bien fermer le fichier si une erreur arrive
+ fclose(fh);
+ throw; // Puis re-lancer l'exception
+ }
+
+ fclose(fh); // Ferme le fichier
+ // Tout s'est déroulé correctement
+}
+
+// Comparez ceci à l'utilisation de la classe de flux de fichier
+// en C++ (fstream).
+// fstream utilise son destructeur pour fermer le fichier.
+// Pour rappel, les destructeurs sont automatiquement appelée dès qu'un objet
+// sort du cadre de sa portée.
+void faireQuelqueChoseAvecUnFichier(const std::string& nomDuFichier)
+{
+ // ifstream is short for input file stream
+ std::ifstream fh(nomDuFichier); // Ouvre le fichier
+
+ // Faire des choses avec le fichier
+ faireQuelqueChoseAvecLeFichier(fh);
+ faireAutreChoseAvec(fh);
+
+} // Le fichier est automatiquement fermé ici par le destructeur
+
+// Ceci a des avantages _énormes_ :
+// 1. Peu importe la situation, la ressource (dans ce cas précis la gestion
+// de fichier) sera libérée. Si le destructeur est écrit correctement,
+// il est _impossible_ d'oublier de fermer la gestion et d'entraîner une
+// une fuite de ressources (si l'objet est sur la pile).
+// 2. Remarquez que le code est beaucoup plus clair.
+// Le destructeur gère la fermeture du fichier discrètement sans avoir
+// besoin de s'en préoccuper.
+// 3. Le code est fiable par rapport aux exceptions.
+// Une exception peut être lancée n'importe où dans la fonction, le
+// nettoyage se fera toujours.
+
+// Tout code C++ idiomatique utilise considérablement RAII pour toutes les
+// ressources.
+// Des exemples additionnels inclus :
+// - La mémoire utilisant unique_ptr et shared_ptr
+// - Des conteneurs (containers) - la liste chaînée de la librairie standard,
+// des vecteurs (c.-à-d. tableaux auto-redimensionnés), tables de hachage, et
+// ainsi de suite. Tous détruisent leur contenu quand ils sortent du cadre
+// de leur portée.
+// - Les mutex utilisant lock_guard et unique_lock
+
+
+//////////////////
+// Divers
+//////////////////
+
+// Ici sont regroupés des aspects du C++ qui peuvent être surprenants aux
+// novices (et même à quelques habitués).
+// Cette section est, malheureusement, grandement incomplète; C++ est un des
+// langages où il est très facile de se tirer soi-même dans le pied.
+
+// Vous pouvez surcharger des méthodes privées !
+class Foo {
+ virtual void bar();
+};
+class FooSub : public Foo {
+ virtual void bar(); // Surcharge Foo::bar!
+};
+
+// 0 == false == NULL (la plupart du temps) !
+bool* pt = new bool;
+*pt = 0; // Affecte false à la valeur de la variable pointée par 'pt'.
+pt = 0; // Affecte le pointeur null à 'pt'.
+// Les deux lignes compilent sans avertissement.
+
+// nullptr est supposé régler un peu ce problème :
+int* pt2 = new int;
+*pt2 = nullptr; // Ne compile pas
+pt2 = nullptr; // Affecte null à pt2
+
+// Il y a une exception faite pour les booléens.
+// Ceci vous permet de tester les pointeurs null avec if(!ptr),
+// mais par conséquent, vous pouvez assigner nullptr à un booléen directement !
+*pt = nullptr; // Ceci compile toujours, même si '*pt' est un booléen !
+
+// '=' != '=' != '='!
+// Appelle Foo::Foo(const Foo&) ou une variante du (voir sémantiques de mouvement)
+// constructeur par copie.
+Foo f2;
+Foo f1 = f2;
+
+// Appelle Foo::Foo(const Foo&) ou une variante, mais copie seulement la partie
+// 'Foo' de 'fooSub'. Tout membre extra de 'fooSub' est ignoré.
+// Ce comportement parfois horrifiant est appelé "object slicing".
+FooSub fooSub;
+Foo f1 = fooSub;
+
+// Appelle Foo::operator=(Foo&) ou une variante.
+Foo f1;
+f1 = f2;
+
+// Comment vraiment nettoyer un conteneur :
+class Foo { ... };
+vector<Foo> v;
+for (int i = 0; i < 10; ++i)
+ v.push_back(Foo());
+
+// La ligne suivante affecte la taille de v à 0, mais les destructeurs ne sont
+// appelés et les ressources ne sont pas libérées !
+v.empty();
+// La nouvelle valeur est copiée dans le premier Foo que nous avons inséré
+v.push_back(Foo());
+
+// Ceci nettoie toutes les valeurs de v. Voir la section à propos des objets
+// temporaires pour comprendre pourquoi cela fonctionne.
+v.swap(vector<Foo>());
+
+```
+Lecture complémentaire :
+
+* Une référence à jour du langage est disponible à [CPP Reference](http://cppreference.com/w/cpp).
+* Des ressources supplémentaires sont disponibles à [CPlusPlus](http://cplusplus.com).
+* Un tutoriel couvrant les bases du langage et la configuration d'un environnement de codage est disponible à l'adresse [TheChernoProject - C ++](https://www.youtube.com/playlist?list=PLlrATfBNZ98dudnM48yfGUldqGD0S4FFb).