Programmer en C++
Des premiers pas à la maîtrise de C++20
Alain Gibaud
Ellipses
I Généralités15
1 À propos de ce livre
17
1.1 À qui s'adresse-t-il ?17
1.2 Que contient-il ?17
1.3 Les exemples18
1.4 Pictogrammes utilisés20
2 Évolution des langages C et C++
21
3 Informations à l'usage des programmeurs débutants
23
3.1 Qu'est-ce qu'un ordinateur ?23
3.2 Langages de programmation31
4 Les environnements de développement
39
4.1 Choix d'un environnement39
4.2 Choix d'un compilateur40
4.3 Exemples d'utilisation du compilateur gcc40
II Débuter avec le langage C43
5 Composition des programmes en langage C
45
5.1 La notion de fonction en programmation45
5.2 La fonction main45
6 Les données et leur type
47
6.1 Variables et constantes47
6.2 Déclaration des variables47
6.3 Qu'est-ce qu'un type ?47
6.4 Les types primitifs48
6.5 Données constantes59
6.6 Données volatiles62
7 Opérateurs
63
7.1 Opérateurs arithmétiques63
7.2 Opérateurs sur bits65
7.3 Opérateurs de décalage66
7.4 Opérateurs logiques67
7.5 Opérateurs relationnels69
7.6 Opérateurs d'affectation70
7.7 Opérateurs relatifs aux pointeurs71
7.8 Opérateurs divers72
7.9 Priorité et associativité des opérateurs75
7.10 Ordre d'évaluation des opérandes76
7.11 Expressions hétérogènes et conversion automatique de type77
7.12 Promotion entière78
8 Fonctions
79
8.1 Fonctions et sous-programmes79
8.2 Paramètres réels et formels80
8.3 Fonctions sans paramètre83
8.4 Sous-programmes (fonctions ne retournant rien)84
8.5 Fonctions à paramètres constants85
8.6 Fonctions inline85
9 Entrées et sorties
87
9.1 Qu'est-ce qu'une entrée ou une sortie ?87
9.2 Sorties : afficher à l'écran avec printf87
9.3 Entrées : saisir des données au clavier avec scan-F90
10 Organiser les données
95
10.1 Tableaux95
10.2 Structures102
10.3 Unions104
10.4 Choisir entre un tableau et une structure105
10.5 Tableaux et structures comme paramètres de fonctions106
11 Instructions
109
11.1 Les prédicats en C109
11.2 Instructions conditionnelles (tests)109
11.3 Instructions de répétition (boucles)112
11.4 Sélection (switch/case/default)118
11.5 Autres instructions contrôlant le flux d'exécution121
III Approfondir le langage C125
12 La fonction main
127
12.1 Arguments des programmes C (et C++)127
12.2 Arguments comportant des caractères blancs129
12.3 Valeur retournée par la fonction main129
12.4 La fonction standard exit129
13 Le préprocesseur du langage C
131
13.1 Qu'est-ce que le préprocesseur ?131
13.2 Inclure un fichier avec #include132
13.3 Définir une macro avec #define133
13.4 Suppression de macro avec #undef138
13.5 Compilation conditionnelle avec #if139
13.6 Autres # directives141
14 Déclarations et définitions
143
14.1 Concepts de déclaration et de définition143
14.2 Concevoir et analyser des déclarations complexes144
15 Visibilité et durée de vie
151
15.1 Visibilité151
15.2 Durée de vie154
16 Pointeurs et tableaux
157
16.1 Arithmétique des pointeurs157
16.2 Relations entre pointeurs et tableaux160
16.3 Alors, tableaux et pointeurs sont la même chose ?162
16.4 Tableaux à indices décalés162
16.5 Tableaux comme paramètres de fonction163
17 Allocation dynamique de mémoire
175
17.1 Contexte175
17.2 La fonction malloc175
17.3 La fonction free176
17.4 La fonction realloc177
17.5 Erreurs relatives à l'allocation dynamique178
17.6 Exemple179
18 Récursivité
183
18.1 Coût de la récursivité184
18.2 Quand utiliser la récursivité ?185
18.3 Exemples186
18.4 Fonctions à la fois inline et récursives190
IV Débuter avec le langage C++191
19 Utiliser C++ sans créer de classe
193
19.1 Différences mineures entre C et C++193
19.2 Invocation de fonctions C à partir de code C++194
19.3 Création de fonctions C à partir de code C++195
19.4 Opérateurs spécifiques195
19.5 Priorité et associativité des opérateurs C++196
19.6 Ordre d'évaluation des opérandes196
19.7 La surcharge des fonctions197
19.8 Fonctions avec arguments à valeur par défaut198
19.9 Espaces de noms (namespace)200
19.10 Introduction aux entrées-sorties sur flux203
19.11 Les références206
19.12 Quelques éléments de C++ moderne (C++11 à C++20)213
19.13 Allocation dynamique de mémoire222
20 Programmation par objets : les concepts
227
20.1 Classes et objets227
20.2 Héritage228
20.3 Encapsulation230
20.4 Polymorphisme231
21 Organisation des classes en C++
233
21.1 Des structures aux classes233
21.2 Encapsulation233
21.3 Modélisation des données234
21.4 Modélisation des comportements234
21.5 Organisation du code des classes236
22 Modéliser un concept : la classe polynôme
239
22.1 Concept à modéliser239
22.2 Données caractérisant ce concept239
22.3 Modéliser les responsabilités : méthodes240
22.4 Différence entre fonction et méthode242
22.5 Le pointeur this243
22.6 Méthodes statiques245
22.7 Méthodes constantes246
22.8 Fonctions, méthodes et classes amies (friend)248
22.9 Méthodes inline250
23 Construction et destruction
253
23.1 Problématique de l'initialisation253
23.2 Construction253
23.3 Destruction263
23.4 Allocation dynamique de mémoire et construction264
23.5 Restitution de mémoire et destruction265
24 Accesseurs
267
24.1 Qu'est-ce qu'un accesseur ?267
24.2 Mutateur simple (setter)267
24.3 Accesseur simple (getter)267
24.4 Accesseur et attributs calculés268
24.5 Accesseur et auto-extensibilité268
24.6 Accesseur pour objet constant271
24.7 Constance physique et logique, attribut mutable272
24.8 const_cast contre mutable273
24.9 Périmètre d'utilisation des accesseurs274
25 Surcharge des opérateurs
275
25.1 Qu'est-ce que la surcharge des opérateurs ?275
25.2 Périmètre de la surcharge275
25.3 Techniques de surcharge276
25.4 Exemple de surcharge d'opérateurs par méthodes278
25.5 Exemple de surcharge d'opérateurs par fonctions279
25.6 Exemple d'utilisation des opérateurs281
25.7 Choisir le mode d'implantation d'un opérateur281
25.8 Choisir le mécanisme de passage des arguments282
25.9 Choisir le mécanisme de passage du résultat de l'opération283
25.10 Les opérateurs importants283
25.11 Autres opérateurs294
26 Conversions de types
303
26.1 Conversion implicite303
26.2 Conversion par constructeur, spécification explicit305
26.3 Conversion par opérateur307
27 Héritage
311
27.1 Réutilisation d'une classe313
27.2 Héritage public314
27.3 Héritage privé317
27.4 Héritage multiple321
28 Polymorphisme
323
28.1 Type statique et type dynamique323
28.2 Méthodes virtuelles324
28.3 Périmètre du polymorphisme325
28.4 Opérateurs polymorphes325
28.5 Polymorphisme et destruction326
28.6 Classes abstraites et interfaces328
28.7 Le polymorphisme en action330
28.8 Du bon usage du polymorphisme336
29 Généricité
339
29.1 Fonctions génériques339
29.2 Comment la généricité fonctionne-t-elle en C++ ?340
29.3 Périmètre de la généricité341
29.4 Instanciations implicite et explicite341
29.5 Classes et structures génériques343
29.6 Composants génériques à paramètres entiers347
29.7 Paramètres de modèles avec valeurs par défaut352
29.8 La généricité en action353
30 Exceptions
365
30.1 Problématique de gestion des erreurs365
30.2 Gestion des erreurs basée sur les exceptions368
31 Bibliothèque d'entrées-sorties
379
31.1 Structure et composition de la bibliothèque379
31.2 Les différents états des flux383
31.3 Les différents modes d'ouverture des flux387
31.4 istream387
31.5 ifstream392
31.6 istringstream393
31.7 ostrean395
31.8 ofstream396
31.9 ostringstream396
31.10 iostream, fstream et stringstream397
31.11 Manipulateurs d'entrées-sorties398
31.12 Créer ses propres manipulateurs404
32 Expressions lambda (lambda-fonctions)
407
32.1 Qu'est-ce qu'une expression lambda ?408
32.2 Expressions lambda « nommées »409
32.3 Expressions lambda génériques410
32.4 Type de retour d'une expression lambda411
32.5 Expression lambda avec paramètres par défaut411
32.6 Capture de contexte dans une expression lambda412
32.7 Exemples415
33 Bibliothèque générique standard (STL)
419
33.1 Qu'est-ce que la STL ?419
33.2 Introduction aux conteneurs419
33.3 Introduction aux itérateurs420
33.4 Propriétés des conteneurs424
34 Conteneurs de la STL
425
34.1 Le conteneur vector425
34.2 Le conteneur deque432
34.3 Le conteneur array437
34.4 Le conteneur string (basic_string<char>)439
34.5 Les conteneurs forward_list et List445
34.6 Les conteneurs map et multimap450
34.7 Les conteneurs unordered_map et unordered_multimap459
34.8 Les conteneurs set et multiset467
34.9 Les conteneurs unordered_set et unordered_multiset468
34.10 Le conteneur stack468
34.11 Le conteneur queue472
34.12 Le conteneur priority_queue473
34.13 Le mandataire span (C++20)477
34.14 Le mandataire string_view480
34.15 La bibliothèque ranges (C++20)483
34.16 Composition de vues486
35 Algorithmes de la STL
489
35.1 Introduction aux algorithmes489
35.2 Algorithmes non modifiants491
35.3 Algorithmes modifiants495
35.4 Algorithmes de partitionnement et de tri503
35.5 Algorithmes sur intervalles triés507
35.6 Algorithmes ensemblistes508
35.7 Algorithmes sur les tas (heaps)512
36 Type initializer_list
515
36.1 Création d'un initializer_list515
36.2 Interface du modèle initializer_list515
36.3 Exemple516
37 Liaison structurée (Structured binding)
517
37.1 Collections autorisant les liaisons structurées518
37.2 Usages typiques520
38 Pointeurs sur membres
521
38.1 Introduction521
38.2 Exemple522
39 Pratiquez le « C++ facile »
527
39.1 Limitez l'usage des pointeurs527
39.2 Passez les paramètres par valeur ou par référence528
39.3 N'utilisez pas le système d'entrées-sorties du C528
39.4 N'utilisez pas les tableaux528
39.5 N'utilisez pas les chaînes de caractères du langage C529
39.6 Limitez l'usage du préprocesseur530
39.7 Ne gérez pas la mémoire vous-même531
39.8 Utilisez les conteneurs de la STL531
39.9 Utilisez les exceptions531
39.10 Pratiquez l'idiome RAM531
V Approfondir le langage C++533
40 Construction et destruction
535
40.1 Les différentes sortes d'objets535
40.2 Construction et destruction d'objets automatiques536
40.3 Construction et destruction d'objets statiques536
40.4 Construction et destruction d'objets dynamiques536
40.5 Construction et destruction d'objets membres ou de base536
40.6 Construction et destruction d'éléments d'un tableau537
40.7 Construction et exception538
41 Allocation dynamique
539
41.1 Opérateur new avec placement539
41.2 Personnaliser new, new[], delete et delete[]541
42 Opérateurs
547
42.1 Opérateur =547
42.2 Opérateurs ++ et --549
42.3 Opérateur ->554
42.4 Opérateur ""558
42.5 Opérateur de comparaison à trois voies <=> (C++20)563
42.6 Repliement d'opérateur568
42.7 Les quatre manières de replier une expression569
42.8 Quelques cas d'utilisation570
42.9 Opérateurs nommés573
43 Transtypages
577
43.1 static_cast577
43.2 const_cast578
43.3 reinterpret_cast578
43.4 dynamic_cast580
44 Identification de type à l'exécution (RTTI)
585
44.1 L'opérateur typeid585
44.2 La classe type_info586
45 Support du polymorphisme
591
45.1 Principe général591
45.2 Organisation de la table des méthodes virtuelles593
45.3 Invocation des méthodes virtuelles594
45.4 Obtention du type d'un objet polymorphe595
45.5 Conclusion596
46 Héritage
597
46.1 Héritage, encapsulation et pointeurs597
46.2 Héritage et passage de paramètres600
46.3 Héritage et affectation601
46.4 Affectation polymorphe603
46.5 Héritage multiple606
46.6 Héritage dynamique615
46.7 Construction et destruction en cas d'héritage multiple ou virtuel624
47 Généricité
625
47.1 Modèles d'alias (alias template)625
47.2 Spécialisation des modèles626
47.3 Spécialisations partielles des modèles627
47.4 Modèles de paramètres de modèles en C++17630
47.5 Guides de déduction632
47.6 Modèles variadlques (variadic templates)636
48 Déduction de type
645
48.1 Déduction de type dans les modèles645
48.2 Déduction de type avec auto648
48.3 Différence entre auto et decltype649
49 Références aux rvalues
653
49.1 rvalue et Ivalue : quelques rappels653
49.2 Passage d'une rvalue en paramètre654
49.3 Références aux rvalues655
49.4 Transmissions par déplacement656
49.5 Conversion en rvalue avec std : : move658
49.6 Méthodes à objet support déplaçable660
50 Transmissions parfaites
663
50.1 Réduction des références et références universelles663
50.2 Transtypage conditionnel avec std : : forward666
50.3 Exemple667
50.4 Les transmissions parfaites dans la STL671
51 Pointeurs intelligents (smart pointers)
673
51.1 Introduction673
51.2 Pourquoi utiliser des pointeurs intelligents ?673
51.3 unique_ptr673
51.4 shared_ptr682
51.5 weak_ptr688
52 Expressions lambda et ciosures
699
52.1 Implantation des expressions lambda699
52.2 Type d'une dosure699
52.3 Rôle des ciosures700
52.4 Capture généralisée701
52.5 Capture par déplacement702
52.6 Expressions lambda et références pendantes703
52.7 Capture par valeur de l'objet support705
52.8 Expressions lambda génériques et transmissions parfaites706
53 Exceptions
709
53.1 Gestion des exceptions non interceptées709
53.2 Spécifications d'exceptions avant C++11710
53.3 Spécifications d'exceptions à partir de C++11711
53.4 Méthodes générées automatiquement et exceptions715
53.5 Écrire du code sûr vis-à-vis des exceptions717
54 Itérateurs
729
54.1 Un itérateur pour le type intervalle729
54.2 Propriétés des différentes catégories d'itérateurs730
54.3 Conception de la classe IRange et de son itérateur730
54.4 Rendre les itérateurs compatibles avec l'écosystème C++734
55 Programmation concurrente et threads
737
55.1 Qu'est-ce qu'un thread ?737
55.2 Premiers pas avec les threads738
55.3 Paramètres de construction d'un thread741
55.4 Les différentes façons d'implanter un thread742
55.5 Threads et exclusion mutuelle744
55.6 Variables de condition et synchronisation749
55.7 jthread (C++20)752
56 Programmation concurrente et tâches
757
56.1 Création d'une tâche avec async757
56.2 Détection de la terminaison d'une tâche758
56.3 Tâches et exceptions759
56.4 Fonctionnement des tâches (promise, future)760
57 Objets exécutables asynchrones
763
57.1 Introduction aux packaged_task763
57.2 Le modèle function763
57.3 Le modèle packaged_task764
57.4 packaged_task et exécution concurrente765
58 Métaprogrammation
767
58.1 Introduction767
58.2 SFINAE769
58.3 Introspection776
58.4 Métaprogrammation et bibliothèque standard780
59 Concepts (C++20)
783
59.1 Utilisation d'un concept prédéfini783
59.2 Création d'un concept784
60 Modules (C++20)
791
60.1 Qu'est-ce qu'un module ?792
60.2 Fichiers décrivant les modules793
60.3 Création d'un module simple793
60.4 Modules et bibliothèque standard795
60.5 Utilisation d'entités non importables796
60.6 Sous-modules798
60.7 Partitions800
60.8 Modularisation d'un composant préexistant803
60.9 Exportation et espaces de noms804
60.10 Conception des modules805