Membres privés, publics, protégés

Nous avons vu au chapitre 6 que certains membres d’une classe pouvaient être publics (les méthodes en général), mais que par défaut ils étaient privés. Pour les structures c’est le contraire.

Il existe une troisième catégorie de membres, les membres protégés (protected). Du point de vue de la classe qui les déclare, ils sont identiques à des membres privés : on ne peut pas y accéder de l’extérieur. Par contre, une classe dérivée peut accéder aux membres protégés de sa classe de base (alors qu’elle ne le peut pas pour les membres privés).

Une classe peut dériver de manière publique d’une classe de base, ou de manière privée. Par défaut, une classe dérive de manière privée, et une structure de manière publique. Voici comment les deux types d’héritages influent sur la nature des membres hérités :

Pour dériver une classe de manière publique, comme ce n’est pas la valeur par défaut, il faut placer le mot public devant le nom de la classe de base. Voici quelques exemples :

class A {     int a1;     protected :     int a2;     public :     int a3;     };class B : A {         // héritage  privé     int b1;     protected :     int b2;     public :     int b3;     };class C : public A { // héritage  public     int c1;     protected :     int c2;     public :     int c3;     };

La classe A possède trois membres, un privé a1, un protégé a2, un public a3 ; de l’extérieur seul a3 est accessible. La classe B possède six membres : un indisponible directement a1, trois privés a2, a3 et b1, un protégé b2 et un public b3 ; de l’extérieur, seul b3 est accessible. Enfin la classe C possède aussi six membres : un indisponible a1, un privé c1, deux protégés a2 et c2 et deux publics a3 et c3 ; de l’extérieur, seuls a3 et c3 sont accessibles.

Pour les structures c’est le contraire, puisque l’héritage est par défaut public. Pour le rendre privé, il suffit de placer le mot private devant le nom de la classe de base. Dans les deux cas, il n’existe pas de dérivation « protégée » .

Il arrive que l’on souhaite modifier ces états par défaut pour un membre ou deux seulement. Dans ce cas, il suffit de renommer les membres hérités en les plaçant au bon endroit. Voici un exemple :

class D : private A {        // héritage  privé     int d1;     protected :     int d2;     A::a2;     public :     int d3;     };class E : public A {        // héritage  public     int e1;     A::a2;     protected :     int e2;     A::a3;     public :     int e3;     };

La classe D, pour laquelle on a précisé un héritage privé (inutilement, c’est la valeur par défaut), diffère de B en ce que le membre hérité a2 est protégé dans D, alors qu’il était privé dans B. La classe E diffère de C en ce que le membre hérité a2 est privé pour elle (protégé pour C) et a3 est protégé pour elle (public pour C).

On ne peut pas diminuer la protection d’un membre par héritage. Si l’on essaie dans une classe dérivée de déclarer public un membre protégé de la classe de base, ou si l’on essaie de redéclarer un membre privé de la classe de base, on obtient une erreur (Error : Access declarations cannot grant or reduce access, les déclarations d’accès ne peuvent pas octroyer ou réduire le niveau d’accès).

Bien que l’héritage des classes soit privé par défaut, il est en général préférable de le déclarer public. Par exemple, notre classe rectplein est mal déclarée à la section précédente, il faut un héritage public :

class rectplein : public rectangle {     // ...     };

Dans le cas contraire, il ne serait pas possible d’appeler les méthodes héritées valeur et change à partir d’une variable de type rectplein.

Pour ce qui est des membres, le choix entre les différents accès n’est pas toujours évident. En effet, s’il est clair que l’on doit déclarer publics les membres (en général seulement des méthodes) que l’on souhaite accessibles de l’extérieur, il n’est pas forcément facile de choisir entre privés et protégés pour les autres, puisque cela exige de réfléchir à ce que pourraient être d’éventuelles classes dérivées de la classe courante. Dans la suite de ce chapitre, nous nous efforcerons de donner quelques indications sur des exemples, car il n’y a pas réellement de règle générale en la matière : cela dépend si l’on souhaite que les classes dérivées connaissent bien le contenu de leur base ou non.

Précédent Précédent Sommaire Sommaire Suivant Suivant