Menu
Coddy logo textTech

Idiom Pimpl

Fait partie de la section Programmation Orientée Objet du Journey C++ de Coddy. Leçon 78 sur 104.

L’idiome Pimpl (Pointer to Implementation) est une technique qui masque les détails d’implémentation d’une classe en les déplaçant dans une classe distincte déclarée au préalable. Cela réduit les dépendances de compilation et maintient les membres privés véritablement masqués du fichier d’en-tête.

L’idée fondamentale est simple : au lieu de déclarer directement les membres privés dans votre classe, vous déclarez un pointeur vers une classe d’implémentation qui est définie uniquement dans le fichier source :

// Widget.h
#include <memory>

class Widget {
public:
    Widget();
    ~Widget();
    void doSomething();
    
private:
    class Impl;  // Déclaration anticipée
    std::unique_ptr<Impl> pImpl;
};
// Widget.cpp
#include "Widget.h"
#include <iostream>

class Widget::Impl {
public:
    int data = 42;
    void process() { std::cout << "Processing: " << data << "\n"; }
};

Widget::Widget() : pImpl(std::make_unique<Impl>()) {}
Widget::~Widget() = default;

void Widget::doSomething() { pImpl->process(); }

Les principaux avantages sont le compilation firewall et la compatibilité binaire. Lorsque vous modifiez la classe Impl, seul le fichier source doit être recompilé — et non chaque fichier qui inclut le header. Cela accélère considérablement les temps de compilation dans les grands projets.

Notez que le destructeur doit être défini dans le fichier source (même s’il est défini par défaut), car unique_ptr a besoin du type complet de Impl pour le supprimer. Il s’agit d’un piège courant lors de la première utilisation de Pimpl.

challenge icon

Défi

Facile

Construisons un gestionnaire de messages sécurisé en utilisant l’idiome Pimpl pour masquer les détails d’implémentation du chiffrement dans le fichier d’en-tête. Cela montre comment Pimpl crée une barrière de compilation : toute personne qui inclut votre fichier d’en-tête ne verra pas le fonctionnement interne du traitement de vos messages.

Vous allez organiser votre code sur trois fichiers :

  • SecureMessage.h : définir l’interface publique de votre classe SecureMessage.

    Votre classe doit avoir une classe Impl déclarée au préalable ainsi qu’un std::unique_ptr vers celle-ci. L’interface publique doit inclure :

    • Un constructeur qui prend un const std::string& pour le message original
    • Un destructeur (qui doit être déclaré ici et défini dans le fichier .cpp)
    • Une méthode setKey(int key) pour définir une clé de chiffrement
    • Une méthode getEncrypted() qui renvoie le message chiffré sous forme de std::string
    • Une méthode getOriginal() qui renvoie le message original

    Le fichier d’en-tête doit uniquement présenter l’interface publique : aucun détail d’implémentation sur le fonctionnement du chiffrement ne doit être visible ici.

  • SecureMessage.cpp : définir la classe imbriquée Impl et implémenter toutes les méthodes.

    Votre classe Impl doit stocker le message original, la clé de chiffrement (avec 0 comme valeur par défaut) et gérer la logique réelle du chiffrement. Utilisez un simple chiffrement de César : décalez chaque caractère selon la valeur de la clé. Par exemple, avec la clé 3, « a » devient « d » et « z » revient à « c ».

    Le chiffrement ne doit affecter que les lettres minuscules (a-z), en laissant tous les autres caractères inchangés. N’oubliez pas de définir le destructeur ici (même s’il est défini par défaut), car unique_ptr a besoin du type Impl complet.

  • main.cpp : lire deux entrées :
    1. Une chaîne représentant un message (qui peut contenir des espaces)
    2. Une clé de chiffrement (un entier)

    Créez un objet SecureMessage, définissez la clé et affichez les résultats :

    1. Afficher Original: suivi du message original
    2. Afficher Encrypted: suivi du message chiffré

Par exemple, avec les entrées hello world et 3 :

Original: hello world
Encrypted: khoor zruog

Avec les entrées xyz abc et 5 :

Original: xyz abc
Encrypted: cde fgh

Remarquez que le fichier d’en-tête ne révèle rien de l’implémentation du chiffrement de César : c’est là toute la puissance de Pimpl. Si vous passiez ultérieurement à un autre algorithme de chiffrement, seul SecureMessage.cpp devrait être recompilé, et non chaque fichier qui inclut le fichier d’en-tête.

Essayez vous-même

#include <iostream>
#include <string>
#include "SecureMessage.h"

int main() {
    // Lire le message (peut contenir des espaces)
    std::string message;
    std::getline(std::cin, message);
    
    // Lire la clé de chiffrement
    int key;
    std::cin >> key;
    
    // TODO: Créer un objet SecureMessage avec le message
    
    // TODO: Définir la clé de chiffrement
    
    // TODO: Afficher "Original: " suivi du message original
    
    // TODO: Afficher "Encrypted: " suivi du message chiffré
    
    return 0;
}
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation Orientée Objet

Entraînez-vous par vous-même : Compilateur C++ en ligne