[24] Héritage - privé et héritage protégé

(Une partie de C++ FAQ Lite fr, Copyright © 1991-2002, Marshall Cline, cline@parashift.com)

Traduit de l'anglais par Stéphane Bailliez

Les FAQs de la section [24]


[24.1] Comment exprime t-on " l'héritage privé"?
Lorsque vous utilisez : privateà la place de : public. E.g.,

class Foo : private Bar {
public:
// ...
};

[ Haut | Bas | Rechercher ]


[24.2] Quelle est la similarité entre "l'héritage privé" et la "composition"?
L'héritage privé est une forme syntaxique de composition (has-a).

Par example, la relation "Car has-a Engine" (une voiture a un moteur) peut être exprimé sous forme de composition:

class Engine {
public:
Engine(int numCylinders);
void start(); // Démarre ce moteur (Engine)
};

class Car {
public:
Car() : e_(8) { } // Initialise cette voiture (Car) avec 8 cylindres
void start() { e_.start(); } // Démarre cette voiture (Car) en démarrant son moteur (Engine)
private:
Engine e_; // Une voiture a un moteur (Car has-a Engine)
};

La même relation "has-a" peut être exprimée en utilisant l'héritage privé:

class Car : private Engine { // Une voiture a un moteur (Car has-a Engine)
public:
Car() : Engine(8) { } // Initialise cette voiture (Car) avec 8 cylindres
Engine::start; // Démarre cette voiture (Car) en démarrant son moteur (Engine)
};

Il y a plusieurs similarités entre ces deux formes de composition:

Il y a également plusieurs distinctions: Notez bien que l'héritage privé est habituellement utilisé pour obtenir l'accés aux membres protégés de la classe de base, mais c'est généralement une solution à court terme (NDT: ?) (en clair: du bidouillage)

[ Haut | Bas | Rechercher ]


[24.3] Quelle doit être ma préférence : composition ou héritage privé?
Utilisez la composition lorsque vous pouvez et l'héritage privé lorsque vous devez.

Normalement il n'est pas souhaitable pour vous d'accéder aux éléments internes de trop d'autres classes, et l'héritage privé vous donne ce petit plus de possibilités (et de responsabilités). Mais l'héritage privé n'est pas à proscrire; il est juste plus lourd à maintenir car il accroit la probabilité que quelqu'un changera quelque chose qui cassera votre code.

Une utilisation légitime et à long terme de l'héritage privé est lorsque que vous souhaitez construire une class Fred qui utilises le code de class Wilma, et le code de class Wilma doit appeler des fonctions membres de votre nouvelle class Fred. Dans ce cas, Fred appelle des fonctions non-virtuelles dans Wilma, et Wilma appelle les fonctions (normalement virtuelles pures) en son sein, qui sont surchargés par Fred. Cela est bien plus difficile a obtenir à l'aide de la composition.

class Wilma {
protected:
void fredCallsWilma()
{
cout << "Wilma::fredCallsWilma()\n";
wilmaCallsFred();
}
virtual void wilmaCallsFred() = 0; // Fonction virtuelle pure
};

class Fred : private Wilma {
public:
void barney()
{
cout << "Fred::barney()\n";
Wilma::fredCallsWilma();
}
protected:
virtual void wilmaCallsFred()
{
cout << "Fred::wilmaCallsFred()\n";
}
};

[ Haut | Bas | Rechercher ]


[24.4] Puis-je caster un pointeur sur une classe dérivée de manière privée en sa classe de base?
[Recently changed PrivateDer to PrivatelyDer in last paragraph (on 10/99).]

Généralement, Non.

Vu de la fonction membre ou d'un ami d'une classe dérivée de manière privée; la relation avec la classe de base est connue et la conversion ascendante de PrivatelyDer* en Base* (ou de PrivatelyDer& en Base&) est sûre; aucun cast n'est nécessaire ou recommandé.

Cependant, les utilisateurs de PrivatelyDer doivent éviter une conversion non-sûre car cela est basé sur une décision privée de PrivatelyDer, et est susceptible de changer sans avertissement.

[ Haut | Bas | Rechercher ]


[24.5] Quelle est le rapport entre l'héritage protégé et l'héritage privé ?
Similarités: Les deux permettent la surcharge des fonctions virtuelles privées/ protégéesde la classe de base, et n'impliquent pas que la classe dérivée soit une généralisation (kind-of) de la classe de base.

Différences: L'héritage protégé permet aux classes dérivées des classes dérivées de connaître la relation d'héritage. Donc, vos petits enfants sont exposés aux détails de votre implémentation. Cela est à la fois un bénéfice (les sous-classes de la classe dérivée protégée peuvent exploiter la relation avec la classe de base protégée) et un coût (la classe dérivée protégée ne peut changer la relation sans potentiellement casser ses classes dérivées).

L'héritage protégée utilise la syntaxe : protected

class Car : protected Engine {
public:
// ...
};

[ Haut | Bas | Rechercher ]


[24.6] Quelles sont les règles d'accés concernant l'héritage privé et protégé ?
[Recently rewritten with the using syntax; thanks to Stephen Vance (on 10/99).]

Prenez l'exemple des classes suivantes::

class B { /*...*/ };
class D_priv : private B { /*...*/};
class D_prot : protected B { /*...*/};
class D_publ : public B { /*...*/};
class UserClass { B b; /*...*/ };

Aucune des classes dérivées ne peut accéder aux parties privées de B. Dans D_priv, les parties publiques et protégées de B sont privées. Dans D_prot, les parties publiques et protégées de B sont protégées. Dans D_publ, les parties publiques de B sont publiques et les parties protégées de B sont protégées (D_publ est kind-of B). La class UserClass peut accéder uniquement aux parties publiques de B, ce qui isole UserClass de B.

Pour avoir un membre public de B qui soit également public dans D_priv ou dans D_prot, préfixez le nom du membre par B::. Par exemple, pour que le membre B::f(int,float) soit public dans D_prot, cela donnerai:

class D_prot : protected B {
public:
using B::f; // Note: Et non pas using B::f(int,float)
};

[ Haut | Bas | Rechercher ]


E-mail Marshall Cline Ecrire à l'auteur, au traducteur, ou en savoir plus sur la traduction.
C++ FAQ Lite fr | Table des matières | Index | A propos de l'auteur | © | Téléchargez votre propre copie ]
Dernière révision Sun Apr 13 23:54:32 PDT 2003