Je ne suis pas un gars en C ++, mais je suis obligé d'y penser. Pourquoi l'héritage multiple est-il possible en C ++, mais pas en C #? (Je connais le problème du diamant , mais ce n'est pas ce que je demande ici). Comment C ++ résout-il l'ambiguïté des signatures de méthodes identiques héritées de plusieurs classes de base? Et pourquoi le même design n'est-il pas incorporé dans C #?
13
Réponses:
Je pense (sans référence précise), qu'en Java, ils voulaient limiter l'expressivité du langage pour le rendre plus facile à apprendre et parce que le code utilisant l'héritage multiple est plus souvent trop complexe pour son propre bien qu'improbable. Et parce que l'héritage multiple complet est beaucoup plus compliqué à implémenter, il a donc beaucoup simplifié la machine virtuelle aussi (l'héritage multiple interagit particulièrement mal avec le ramasse-miettes, car il nécessite de garder des pointeurs au milieu de l'objet (au début de la base) )
Et lors de la conception de C #, je pense qu'ils ont regardé Java, ont vu que l'héritage multiple complet n'était en effet pas beaucoup manqué et ont choisi de garder les choses simples aussi.
Ce n'est pas le cas . Il existe une syntaxe pour appeler explicitement la méthode de la classe de base à partir d'une base spécifique, mais il n'y a aucun moyen de remplacer une seule des méthodes virtuelles et si vous ne remplacez pas la méthode dans la sous-classe, il n'est pas possible de l'appeler sans spécifier la base classe.
Il n'y a rien à incorporer.
Puisque Giorgio a mentionné les méthodes d'extension d'interface dans les commentaires, je vais expliquer ce que sont les mixins et comment ils sont implémentés dans différentes langues.
Les interfaces en Java et C # se limitent à déclarer des méthodes uniquement. Mais les méthodes doivent être implémentées dans chaque classe qui hérite de l'interface. Il existe cependant une grande classe d'interfaces, où il serait utile de fournir des implémentations par défaut de certaines méthodes en termes d'autres. Un exemple courant est comparable (en pseudo-langage):
La différence avec la classe complète est qu'elle ne peut contenir aucun membre de données. Il existe plusieurs options pour l'implémenter. De toute évidence, l'héritage multiple en est un. Mais l'héritage multiple est plutôt compliqué à mettre en œuvre. Mais ce n'est pas vraiment nécessaire ici. Au lieu de cela, de nombreux langages implémentent cela en divisant le mixin dans une interface, qui est implémentée par la classe et un référentiel d'implémentations de méthodes, qui sont soit injectées dans la classe elle-même, soit une classe de base intermédiaire est générée et y est placée. Ceci est implémenté dans Ruby et D , sera implémenté dans Java 8 et peut être implémenté manuellement en C ++ en utilisant le modèle de modèle curieusement récurrent . Ce qui précède, sous forme de CRTP, ressemble à:
et s'utilise comme:
Cela ne nécessite rien d'être déclaré virtuel comme le ferait une classe de base normale, donc si l'interface est utilisée dans des modèles, les options d'optimisation utiles restent ouvertes. Notez qu'en C ++, cela serait probablement encore hérité en tant que deuxième parent, mais dans les langages qui n'autorisent pas l'héritage multiple, il est inséré dans la chaîne d'héritage unique, donc c'est plus comme
L'implémentation du compilateur peut ou non éviter la répartition virtuelle.
Une implémentation différente a été sélectionnée en C #. En C #, les implémentations sont des méthodes statiques de classe complètement distincte et la syntaxe d'appel de méthode est correctement interprétée par le compilateur si une méthode de nom donné n'existe pas, mais une "méthode d'extension" est définie. Cela a l'avantage que des méthodes d'extension peuvent être ajoutées à une classe déjà compilée et l'inconvénient que ces méthodes ne peuvent pas être remplacées, par exemple pour fournir une version optimisée.
la source
La réponse est qu'elle ne fonctionne pas correctement en C ++ en cas de conflits d'espace de noms. Regardez ça . Pour éviter les conflits d'espace de noms, vous devez faire toutes sortes de girations avec des pointeurs. J'ai travaillé chez MS sur l'équipe Visual Studio et j'ai au moins en partie la raison pour laquelle ils ont développé la délégation était d'éviter la collision d'espace de noms. Avant, j'avais dit qu'ils considéraient également les interfaces comme faisant partie de la solution d'héritage multiple, mais je me trompais. Les interfaces sont réellement incroyables et peuvent être conçues pour fonctionner en C ++, FWIW.
La délégation traite spécifiquement de la collision d'espace de noms: vous pouvez déléguer à 5 classes et les 5 d'entre elles exporteront leurs méthodes vers votre portée en tant que membres de première classe. À l'extérieur, la recherche dans cet héritage multiple est.
la source