En C ++, une classe peut hériter (directement ou indirectement) de plusieurs classes, ce que l'on appelle l'
héritage multiple .
Cependant, C # et Java limitent les classes à un seul héritage, chaque classe hérite d'une seule classe parente.
L'héritage multiple est un moyen utile de créer des classes qui combinent des aspects de deux hiérarchies de classes disparates, ce qui se produit souvent lors de l'utilisation de différents frameworks de classes dans une seule application.
Si deux frameworks définissent leurs propres classes de base pour les exceptions, par exemple, vous pouvez utiliser l'héritage multiple pour créer des classes d'exceptions qui peuvent être utilisées avec l'un ou l'autre framework.
Le problème de l'héritage multiple est qu'il peut conduire à une ambiguïté. L'exemple classique est lorsqu'une classe hérite de deux autres classes, dont chacune hérite de la même classe:
class A {
protected:
bool flag;
};
class B : public A {};
class C : public A {};
class D : public B, public C {
public:
void setFlag( bool nflag ){
flag = nflag; // ambiguous
}
};
Dans cet exemple, le flag
membre de données est défini par class A
. Mais class D
descend de class B
et class C
, qui dérivent tous deux de A
, donc, en substance, deux copies de flag
sont disponibles parce que deux instances de A
sont dans D
la hiérarchie de classes de. Lequel souhaitez-vous définir? Le compilateur se plaindra que la référence à flag
dans D
est ambiguë . Un correctif consiste à clarifier explicitement la référence:
B::flag = nflag;
Un autre correctif consiste à déclarer B et C comme virtual base classes
, ce qui signifie qu'une seule copie de A peut exister dans la hiérarchie, éliminant toute ambiguïté.
D'autres complexités existent avec l'héritage multiple, telles que l'ordre dans lequel les classes de base sont initialisées lorsqu'un objet dérivé est construit, ou la façon dont les membres peuvent être masqués par inadvertance des classes dérivées. Pour éviter ces complexités, certains langages se limitent au modèle d'héritage unique plus simple.
Bien que cela simplifie considérablement l'héritage, cela limite également son utilité car seules les classes avec un ancêtre commun peuvent partager des comportements. Les interfaces atténuent quelque peu cette restriction en permettant aux classes de différentes hiérarchies d'exposer des interfaces communes même si elles ne sont pas implémentées en partageant du code.