J'ai cherché autour de celui-ci, et la réponse commune à cela semble aller dans le sens "ils ne sont pas liés et l'un ne peut pas être substitué à l'autre". Mais disons que vous êtes dans une interview et qu'on vous demande "Quand utiliseriez-vous un modèle au lieu de l'héritage et vice versa?"
Selon moi, les modèles et l'héritage sont des concepts littéralement orthogonaux: l'héritage est "vertical" et descend, de l'abstrait au plus concret. Une forme, un triange, un triangle équilatéral.
Les modèles en revanche sont "horizontaux" et définissent parallèles des instances de code qui ne se connaissent pas. Le tri des entiers est formellement le même que le tri des doubles et des chaînes de tri, mais ce sont trois fonctions entièrement différentes. Ils "se ressemblent" tous de loin, mais ils n'ont rien à voir les uns avec les autres.
L'héritage fournit une abstraction d'exécution. Les modèles sont génération de code outils.
Parce que les concepts sont orthogonaux, ils peuvent heureusement être utilisés ensemble pour travailler vers un objectif commun. Mon exemple préféré est type erasure, dans lequel le conteneur d'effacement de type contient un pointeur de base virtuel vers une classe d'implémentation, mais il existe arbitrairement de nombreuses implémentations concrètes générées par une classe dérivée de modèle. La génération de code de modèle sert à remplir une hiérarchie d'héritage. La magie.
La "réponse commune" est fausse. Dans "C++ efficace", Scott Meyers dit dans l'article 41:
Item 41: Comprendre les interfaces implicites et le polymorphisme au moment de la compilation.
Meyers poursuit en résumant:
- Les classes et les modèles prennent en charge les interfaces et le polymorphisme.
- Pour les classes, les interfaces sont explicites et centrées sur les signatures de fonction. Le polymorphisme se produit lors de l'exécution via des fonctions virtuelles.
- Pour les paramètres de modèle, les interfaces sont implicites et basées sur des expressions valides. Le polymorphisme se produit lors de la compilation via l'instanciation du modèle et la résolution de surcharge de fonction.
utiliser un modèle dans une base (ou composition) lorsque vous souhaitez conserver la sécurité des types ou souhaitez éviter la répartition virtuelle.
Les modèles sont appropriés lors de la définition d'une interface qui fonctionne sur plusieurs types d'objets non liés. Les modèles sont parfaitement adaptés aux classes de conteneur où il est nécessaire de généraliser les objets dans le conteneur, tout en conservant les informations de type.
En cas d'héritage, tous les paramètres doivent être du type de paramètre défini ou s'étendre à partir de celui-ci. Ainsi, lorsque les méthodes fonctionnent sur des objets qui ont correctement une relation hiérarchique directe, l'héritage est le meilleur choix.
Lorsque l'héritage est incorrectement appliqué, cela nécessite de créer des hiérarchies de classes trop complexes, d'objets non liés. La complexité du code augmentera pour un petit gain. Si tel est le cas, utilisez des modèles.
Le modèle décrit un algorithme comme décider du résultat d'une comparaison entre les deux objets d'une classe ou les trier. Le type (classe) d'objets opérés varie, mais l'opération, la logique ou l'étape, etc., est logiquement la même.
L'héritage, d'autre part, est utilisé par la classe enfant uniquement pour étendre ou rendre plus spécifique la fonctionnalité des parents. Un espoir qui a du sens