ProgrammationDéveloppeur C++

Qu'est-ce que la délégation de responsabilité (delegation) par composition en C++ ? En quoi la composition diffère-t-elle de l'héritage et quand utiliser chacun de ces approches ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

La délégation de responsabilité par composition est une pratique de programmation où un objet d'une classe contient un objet d'une autre classe (ou classes) et utilise ces objets pour implémenter une partie de sa logique, au lieu d'hériter de leur interface.

Historique de la question

Les premières versions de la POO mettaient l'accent sur l'héritage, mais avec le temps, la pratique a montré que la composition offre souvent une plus grande flexibilité, extensibilité et réduction de couplage entre les composants.

Problème

L'héritage lie les objets de manière rigide : les modifications dans la classe de base impactent tous les héritiers, les hiérarchies deviennent complexes et l'architecture fragile. La composition élimine ces problèmes, permettant de construire des systèmes plus fiables et maintenables.

Solution

En C++, la délégation est réalisée en incluant un objet d'une classe comme membre d'une autre classe. Dans la classe enveloppante, les méthodes de l'objet imbriqué sont appelées.

Exemple de code :

class Logger { public: void log(const std::string& msg) { std::cout << msg << std::endl; } }; class FileProcessor { Logger logger; // Composition public: void process(const std::string& filename) { logger.log("Traitement du fichier : " + filename); // ... } };

Caractéristiques clés :

  • Couplage plus faible, flexibilité
  • Possibilité de changer l'objet délégué à la volée
  • Plus facile à tester et maintenir

Questions piégées.

La composition peut-elle remplacer complètement l'héritage ?

Non, l'héritage est nécessaire là où une relation "est un" (is-a) est requise, la composition — lorsque "a" (has-a). Par exemple, Button hérite de Widget, mais Car "a" Engine (composition).

Peut-on dans la composition modifier le comportement de la méthode déléguée ?

Oui, les méthodes de délégation peuvent être adaptées sans toucher à la classe de base. De plus, l'objet délégué peut être changé dynamiquement (par exemple, via un pointeur ou un pointeur unique).

La composition est-elle plus lente que l'héritage ?

Non, il n'y a pas de différence de performance dans la plupart des cas. Parfois, l'héritage ajoute des frais à cause des appels virtuels (vtable), tandis que la composition n'augmente que la taille de l'objet.

Erreurs typiques et anti-patterns

  • Utilisation de l'héritage là où la composition suffirait
  • Complexification excessive de la composition avec des objets imbriqués sans nécessité
  • "Gonflement" des classes avec de multiples dépendances fragmentées

Exemple de la vie réelle

Cas négatif

Dans le projet, toutes les fenêtres de dialogue hérité d'un DialogWindow commun. L'ajout de nouvelles logiques métier entraînait un code non fonctionnel dans tous les héritiers.

Avantages :

  • Création rapide au départ
  • Réutilisation du code

Inconvénients :

  • Structure rigide
  • Tout changement affecte tout l'arbre

Cas positif

Les fonctions communes ont été extraites dans des classes séparées (journalisation, validation) qui sont injectées dans chaque dialogue par composition.

Avantages :

  • Flexibilité
  • Remplacement facile du comportement

Inconvénients :

  • Nécessite une conception supplémentaire
  • Peut conduire à une surdétaillé