Le problème le plus évident est celui de la surcharge des fonctions.
Supposons que nous ayons deux classes A
y B
qui définissent tous deux une méthode doSomething
. Vous définissez maintenant une troisième classe C
qui hérite à la fois de A
y B
mais vous n'avez pas la possibilité de remplacer le doSomething
méthode.
Lorsque le compilateur sème ce code...
C c = new C();
c.doSomething();
...quelle implémentation de la méthode doit-il utiliser ? Sans autre précision, il est impossible pour le compilateur de lever l'ambiguïté.
Outre la surcharge, l'autre grand problème de l'héritage multiple est la disposition des objets physiques dans la mémoire.
Les langages tels que C++, Java et C# créent une disposition fixe basée sur l'adresse pour chaque type d'objet. C'est à peu près cela :
class A:
at offset 0 ... "abc" ... 4 byte int field
at offset 4 ... "xyz" ... 8 byte double field
at offset 12 ... "speak" ... 4 byte function pointer
class B:
at offset 0 ... "foo" ... 2 byte short field
at offset 2 ... 2 bytes of alignment padding
at offset 4 ... "bar" ... 4 byte array pointer
at offset 8 ... "baz" ... 4 byte function pointer
Lorsque le compilateur génère le code machine (ou bytecode), il utilise ces décalages numériques pour accéder à chaque méthode ou champ.
L'héritage multiple rend les choses très difficiles.
Si la classe C
hérite à la fois de A
y B
le compilateur doit décider s'il faut disposer les données en AB
dans l'ordre ou dans BA
l'ordre.
Mais imaginez maintenant que vous appeliez des méthodes sur un fichier B
objet. S'agit-il vraiment d'un B
? Ou s'agit-il en fait d'un C
appelé de manière polymorphe, par l'intermédiaire de son objet B
l'interface ? En fonction de l'identité réelle de l'objet, la disposition physique sera différente, et il est impossible de connaître l'offset de la fonction à invoquer sur le site d'appel.
La façon de gérer ce type de système est d'abandonner l'approche de la disposition fixe, en permettant à chaque objet d'être interrogé sur sa disposition avant en essayant d'invoquer les fonctions ou d'accéder à ses champs.
Donc... pour faire court... c'est un casse-tête pour les auteurs de compilateurs de prendre en charge l'héritage multiple. Ainsi, lorsque Guido van Rossum conçoit Python ou Anders Hejlsberg conçoit C#, ils savent que la prise en charge de l'héritage multiple va rendre l'implémentation du compilateur beaucoup plus complexe et, vraisemblablement, ils ne pensent pas que l'avantage en vaut le coût.
56 votes
Je voudrais juste mentionner que C++ est excellent pour vous donner assez de corde pour vous pendre.
1 votes
Pour une alternative à l'héritage multiple qui aborde (et, IMHO, résout) un grand nombre des mêmes problèmes, regardez les Traits ( iam.unibe.ch/~scg/Recherche/Traits )
53 votes
Je pensais que C++ vous donnait suffisamment de marge de manœuvre pour vous tirer une balle dans le pied.
6 votes
Cette question semble supposer qu'il y a un problème avec l'IM en général, alors que j'ai trouvé beaucoup de langues où l'IM est utilisé occasionnellement. Il y a certainement des problèmes avec la gestion de l'IM dans certaines langues, mais je ne suis pas au courant que l'IM en général pose des problèmes significatifs.