Chargement...

Encapsulation et modificateurs d’accès en C++ (public, protected, private)

Apprenez l’encapsulation et les modificateurs d’accès en C++ pour concevoir des classes sûres et maintenables.

Encapsulation (Encapsulation) est l’un des quatre principes fondamentaux de la programmation orientée objet (POO). Elle consiste à cacher les données (attributs) d’une classe au monde extérieur et à y accéder uniquement par des méthodes définies. Cette approche garantit l’intégrité des données et rend la structure interne d’une classe indépendante de son utilisation externe.


1) Qu’est-ce que l’encapsulation ?

L’encapsulation est le principe de « cacher les données ». Les détails internes d’une classe (attributs, méthodes auxiliaires) sont cachés à l’extérieur. L’utilisateur interagit uniquement via l’interface publique de la classe.

Avantages de l’encapsulation :


2) Modificateurs d’accès

En C++, il existe trois types de modificateurs d’accès :

Modificateur Niveau d’accès Utilisation
public Accessible partout Interface publique de la classe (API)
protected Accessible uniquement dans la classe et les classes dérivées Comportements communs utilisés en héritage
private Accessible uniquement à l’intérieur de la classe Champs de données, fonctions utilitaires

3) Exemple d’encapsulation avec la classe Book

Voici un exemple d’une classe Book illustrant le principe d’encapsulation.


#include <iostream>
#include <string>
using namespace std;

class Book {
private:
    string title;
    string author;
    double price;
    int pageCount;

public:
    // Constructeur
    Book(string t, string a, double p, int pc)
        : title(t), author(a), price(p), pageCount(pc) {}

    // Getters et Setters
    string GetTitle() const { return title; }
    string GetAuthor() const { return author; }

    double GetPrice() const { return price; }
    void SetPrice(double p) {
        if (p >= 0) price = p;
        else cout << "Le prix ne peut pas être négatif !" << endl;
    }

    int GetPageCount() const { return pageCount; }

    void Print() const {
        cout << "Livre : " << title
             << " | Auteur : " << author
             << " | Pages : " << pageCount
             << " | Prix : " << price << " €" << endl;
    }
};

int main() {
    Book b("C++ Primer", "Lippman", 180.0, 950);

    b.Print();
    b.SetPrice(-50); // Invalide
    b.SetPrice(210);
    b.Print();
}

Les champs private ne peuvent pas être modifiés directement. La modification doit se faire via des méthodes contrôlées comme SetPrice().


4) Champs protégés et héritage

Les classes dérivées peuvent accéder directement aux champs protected. Cela permet à la sous-classe d’étendre ou de réutiliser les données de la classe de base.


class EBook : public Book {
protected:
    string format; // Ex. : PDF, EPUB

public:
    EBook(string t, string a, double p, int pc, string f)
        : Book(t, a, p, pc), format(f) {}

    void PrintWithFormat() const {
        cout << GetTitle() << " (" << format << ")" << endl;
    }
};

Ici, la classe dérivée ajoute une nouvelle propriété (format) sans violer le principe d’encapsulation.


5) Le mot-clé friend

Normalement, les membres private ne sont accessibles qu’à l’intérieur de la classe elle-même. Cependant, il peut être nécessaire qu’une autre classe ou fonction accède à ces données privées. Dans ce cas, on peut utiliser une déclaration friend.


class Book {
private:
    string title;
    double price;
public:
    Book(string t, double p) : title(t), price(p) {}

    // Déclaration d'une fonction amie
    friend void ApplyDiscount(Book& b, double rate);
};

void ApplyDiscount(Book& b, double rate) {
    b.price *= (1 - rate); // accès au membre privé
}

int main() {
    Book b("Design Patterns", 300);
    ApplyDiscount(b, 0.1);
}

L’utilisation de friend doit être faite avec précaution, car elle rompt l’encapsulation. Elle ne devrait être utilisée que lorsque c’est nécessaire (par exemple : surcharge d’opérateurs, outils de débogage).


6) Principes de conception pour les getters et setters


class Book {
private:
    string title;
    double price;
public:
    Book(string t, double p) : title(t), price(p) {}

    string GetTitle() const { return title; } // lecture seule
    void ApplyDiscount(double rate) { price *= (1 - rate); } // comportement au lieu d’un setter
};

7) Sécurité des données avec le mot-clé const

Les méthodes const ne modifient pas l’état de la classe. Cela soutient l’encapsulation et empêche les modifications inattendues.


class SafeBook {
private:
    string title;
public:
    SafeBook(string t) : title(t) {}

    string GetTitle() const { return title; } // méthode const
    void SetTitle(string t) { title = t; }
};

Une méthode Get écrite sans const viole ce principe et peut entraîner des erreurs inattendues.


8) Le modèle d’objet immuable (Immutable)

Conformément au principe d’encapsulation, certains objets sont conçus pour être « immuables ». Tous leurs membres sont déclarés const et aucun setter n’est défini.


class ImmutableBook {
private:
    const string title;
    const string author;
    const int pages;
public:
    ImmutableBook(string t, string a, int p)
        : title(t), author(a), pages(p) {}

    string GetTitle() const { return title; }
    string GetAuthor() const { return author; }
    int GetPages() const { return pages; }
};

Cette approche garantit l’intégrité des données, notamment dans les environnements multithread.


9) Encapsulation et gestion de l’état des objets

L’encapsulation ne consiste pas seulement à contrôler l’accès, mais aussi à garantir que l’objet reste dans un état valide. L’état interne de la classe doit toujours avoir des valeurs cohérentes.


class ValidatedBook {
private:
    double price;
public:
    void SetPrice(double p) {
        if (p < 0) throw invalid_argument("Le prix ne peut pas être négatif.");
        price = p;
    }
};

Ces mécanismes de validation garantissent que la classe reste dans un « état valide » et empêchent l’injection de données incorrectes depuis l’extérieur.


10) TL;DR

  • L’encapsulation consiste à cacher les données et à y accéder via des comportements contrôlés.
  • private : accessible uniquement à l’intérieur de la classe.
  • protected : accessible dans la classe et ses sous-classes.
  • public : accessible partout (interface publique).
  • friend permet un accès externe aux données privées (à utiliser avec prudence).
  • La validation et l’utilisation de const dans les getters/setters sont essentielles.
  • Les objets immuables assurent la sécurité des données.
  • L’encapsulation est un principe fondamental pour des conceptions maintenables et fiables.
  • Tous les exemples peuvent être exécutés avec Visual Studio 2022 ou GCC 11+.

Articles connexes