8.4. Encapsulation des données

Les divers champs d'une structure sont accessibles en n'importe quel endroit du programme. Une opération telle que celle-ci est donc faisable :

clientele[0].Solde = 25000;

Le solde d'un client peut donc être modifié sans passer par une méthode dont ce serait le but. Elle pourrait par exemple vérifier que l'on n'affecte pas un solde supérieur au solde maximal autorisé par le programme (la borne supérieure des valeurs des entiers signés). Par exemple, si les entiers sont codés sur 16 bits, cette borne maximum est 32767. Un programme qui ferait :

clientele[0].Solde = 32800;
obtiendrait donc un solde de -12 (valeur en nombre signé du nombre non signé 32800), alors qu'il espérerait obtenir un solde positif !

Il est possible d'empêcher l'accès des champs ou de certaines méthodes à toute fonction autre que celles de la classe. Cette opération s'appelle l'encapsulation. Pour la réaliser, il faut utiliser les mots clés suivants :

Pour changer les droits d'accès des champs et des méthodes d'une classe, il faut faire précéder ceux-ci du mot clé indiquant les droits d'accès suivi de deux points (':'). Par exemple, pour protéger les données relatives au client, on changera simplement la déclaration de la classe en :

struct client
{
private:   // Données privées :

    char Nom[21], Prenom[21];
    unsigned int Date_Entree;
    int Solde;
    // Il n'y a pas de méthode privée.

public:    // Les données et les méthodes publiques :

    // Il n'y a pas de donnée publique.
    bool dans_le_rouge(void);
    bool bon_client(void)
};

Outre la vérification de la validité des opérations, l'encapsulation a comme intérêt fondamental de définir une interface stable pour la classe au niveau des méthodes et données membres publiques et protégées. L'implémentation de cette interface, réalisée en privé, peut être modifiée à loisir sans pour autant perturber les utilisateurs de cette classe, tant que cette interface n'est pas elle-même modifiée.

Par défaut, les classes construites avec struct ont tous leurs membres publics. Il est possible de déclarer une classe dont tous les éléments sont par défaut privés. Pour cela, il suffit d'utiliser le mot clé class à la place du mot clé struct.

Exemple 8-4. Utilisation du mot clé class

class client
{
    // private est à présent inutile.

    char Nom[21], Prenom[21];
    unsigned int Date_Entree;
    int Solde;

public:    // Les données et les méthodes publiques.

    bool dans_le_rouge(void);
    bool bon_client(void);
};

Enfin, il existe un dernier type de classe, que je me contenterai de mentionner : les classes union. Elles se déclarent comme les classes struct et class, mais avec le mot clé union. Les données sont, comme pour les unions du C, situées toutes au même emplacement, ce qui fait qu'écrire dans l'une d'entre elle provoque la destruction des autres. Les unions sont très souvent utilisées en programmation système, lorsqu'un polymorphisme physique des données est nécessaire (c'est-à-dire lorsqu'elles doivent être interprétées de différentes façons selon le contexte).

Note : Les classes de type union ne peuvent pas avoir de méthodes virtuelles et de membres statiques. Elles ne peuvent pas avoir de classes de base, ni servir de classe de base. Enfin, les unions ne peuvent pas contenir des références, ni des objets dont la classe a un constructeur non trivial, un constructeur de copie non trivial ou un destructeur non trivial. Pour toutes ces notions, voir la suite du chapitre.

Les classes définies au sein d'une autre classe sont considérées comme faisant partie de leur classe hôte, et ont donc le droit d'accéder aux données membres private et protected de celle-ci. Remarquez que cette règle est assez récente dans la norme du langage, et que la plupart des compilateurs refuseront ces accès. Il faudra donc déclarer amies de la classe hôte les classes qui sont définies au sein de celle-ci. La manière de procéder sera décrite dans la Section 8.7.2.