🔝 Retour au Sommaire
🎯 Niveau : Débutant-Intermédiaire
Ce module introduit le paradigme objet en C++ en s'appuyant directement sur la gestion mémoire du module précédent. Classes, RAII, Rule of Five, héritage, polymorphisme dynamique via vtable, et surcharge d'opérateurs — y compris l'opérateur spaceship <=> (C++20). L'objectif n'est pas d'apprendre l'OOP en général, mais de comprendre comment C++ l'implémente, quel coût cela représente en mémoire et en performance, et quelles erreurs spécifiques au langage il faut éviter.
- Implémenter des classes avec constructeurs (défaut, paramétré, copie, déplacement), destructeurs, listes d'initialisation, et modificateurs d'accès (
public,private,protected). - Appliquer le principe RAII pour lier la durée de vie des ressources à celle des objets.
- Maîtriser la Rule of Five : destructeur, constructeur de copie, opérateur d'affectation par copie, constructeur de déplacement, opérateur d'affectation par déplacement.
- Comprendre le mécanisme de vtable et le coût runtime du polymorphisme dynamique (
virtual,override,final). - Concevoir des hiérarchies de classes avec héritage simple, multiple, et virtuel, en évitant le problème du diamant.
- Implémenter la surcharge d'opérateurs (arithmétiques, affectation, conversion, appel de fonction) et utiliser l'opérateur spaceship
<=>(C++20) pour générer automatiquement les comparaisons.
- Module 2, chapitre 5 : gestion mémoire (stack vs heap,
new/delete, pointeurs, dangling pointers) — sans cette base, RAII et la Rule of Five n'ont pas de sens. - Module 2, chapitre 4 : passage de paramètres par valeur, référence et pointeur — utilisé dans chaque constructeur et opérateur de ce module.
- Module 2, chapitre 3 :
const,constexpr, portée et durée de vie des variables.
Conception de classes C++ depuis la définition des membres jusqu'à la Rule of Five. Ce chapitre est le plus long du module — il couvre l'ensemble du cycle de vie d'un objet et le principe RAII qui est la stratégie centrale de gestion des ressources en C++ moderne.
- Définition de classes : membres de données, méthodes, séparation interface/implémentation.
- Constructeurs : par défaut, paramétré, de copie, de déplacement, avec liste d'initialisation (member initializer list) pour éviter la construction par défaut suivie d'une affectation.
- Destructeurs et RAII : acquisition de ressource dans le constructeur, libération dans le destructeur — appliqué aux file descriptors, mémoire dynamique, locks.
- Modificateurs d'accès :
public,private,protected— quand utiliser chacun et pourquoiprivatepar défaut. - Rule of Five : si vous définissez l'un des cinq (destructeur, copy constructor, copy assignment, move constructor, move assignment), vous devez définir ou explicitement
= default/= deleteles quatre autres.
Héritage et polymorphisme dynamique avec un focus sur le mécanisme sous-jacent (vtable) et son coût. Ce chapitre ne se contente pas de montrer la syntaxe — il explique ce que le compilateur génère et ce que ça coûte à l'exécution.
- Héritage simple : dérivation, accès aux membres de la classe de base, constructeurs de la classe dérivée.
- Héritage multiple et problème du diamant : quand deux classes de base partagent un ancêtre commun — résolu par l'héritage virtuel.
- Fonctions virtuelles et vtable : comment le compilateur implémente le dispatch dynamique, taille du vptr, indirection à l'appel.
virtual,override,final:overridepour la vérification compile-time,finalpour interdire la redéfinition ou la dérivation.- Classes abstraites et interfaces pures : fonctions virtuelles pures (
= 0), classes non instanciables. - Coût du polymorphisme dynamique : surcoût mémoire (vptr par objet), surcoût CPU (indirection, impossibilité d'inlining), impact sur la prédiction de branchement.
Surcharge des opérateurs pour donner un comportement naturel aux types personnalisés. Ce chapitre couvre les opérateurs classiques et introduit l'opérateur spaceship <=> (C++20) qui simplifie la génération des six opérateurs de comparaison.
- Opérateurs arithmétiques (
+,-,*,/) et de comparaison (==,!=,<,>) : implémentation comme membre ou fonction libre, cohérence entre opérateurs. - Opérateurs d'affectation (
=,+=,-=, etc.) : lien avec la Rule of Five pouroperator=. - Opérateurs de conversion :
operator int(),explicit operator bool()— contrôle des conversions implicites. operator(): foncteurs (callable objects), utilisés comme prédicats dans les algorithmes STL.- Opérateur spaceship
<=>(C++20) : déclaration d'un seul opérateur pour générer automatiquement==,!=,<,<=,>,>=— avec les catégories de comparaison (strong_ordering,weak_ordering,partial_ordering).
-
Destructeur virtuel manquant sur une classe de base. Si une classe est destinée à être dérivée et que des objets dérivés sont détruits via un pointeur vers la base, le destructeur de la base doit être
virtual. Sans ça, seul le destructeur de la base est appelé — le destructeur de la classe dérivée n'est jamais exécuté, ce qui cause des fuites de ressources. C'est un bug silencieux que ni le compilateur ni les sanitizers ne détectent systématiquement. Règle simple : si votre classe a au moins une fonction virtuelle, son destructeur doit l'être aussi. -
Rule of Five partielle. Implémenter le move constructor sans le copy constructor (ou l'inverse) laisse la classe dans un état incohérent. Si vous définissez un move constructor mais pas de copy constructor, le compilateur supprime implicitement le copy constructor — votre classe devient non copiable sans que ce soit intentionnel. Définissez ou
= default/= deleteles cinq explicitement. -
Slicing problem. Passer un objet dérivé par valeur à une fonction qui prend la classe de base coupe (slice) les membres de la classe dérivée. L'objet reçu est une copie tronquée à la base. Le polymorphisme est perdu. Solution : passer par référence (
const Base&) ou par pointeur (Base*), jamais par valeur quand le polymorphisme est attendu. -
Surcharge d'opérateur qui viole les attentes sémantiques. Surcharger
operator+pour qu'il modifie l'objet gauche (au lieu de retourner un nouvel objet) ou surchargeroperator==de manière non symétrique crée du code qui se comporte de façon inattendue. Les opérateurs doivent respecter les conventions mathématiques :a + bne modifie nianib,a == bimpliqueb == a. L'opérateur spaceship<=>(C++20) élimine une partie de ce risque en générant les comparaisons de manière cohérente.
À l'issue de ce module, vous savez :
- Concevoir des classes C++ avec gestion correcte du cycle de vie (constructeurs, destructeur, Rule of Five).
- Appliquer RAII pour garantir la libération des ressources sans gestion manuelle.
- Implémenter une hiérarchie de classes avec polymorphisme dynamique et évaluer son coût en performance.
- Choisir entre héritage simple, multiple, et virtuel selon le problème.
- Surcharger les opérateurs de manière cohérente et idiomatique, y compris avec
<=>(C++20). - Identifier et éviter les bugs classiques de l'OOP C++ : destructeur non virtuel, slicing, Rule of Five partielle.