Modèles et polymorphisme en C
Considérez la structure de classe suivante :
<code class="cpp">class Interface { // ... }; class Foo : public Interface { // ... }; template <class T> class Container { // ... };</code>
Un constructeur d'une autre classe Bar est défini comme :
<code class="cpp">Bar(const Container<Interface>& bar) { // ... }</code>
Cependant, lorsque vous tentez d'appeler le constructeur comme suit :
<code class="cpp">Container<Foo> container(); Bar *temp = new Bar(container);</code>
nous rencontrons une erreur "aucune fonction de correspondance".
Polymorphisme dans les modèles
Le concept de polymorphisme dans les modèles, ou covariance des modèles, impliquerait que si la classe B hérite de la classe A, alors T hérite également de T. Cependant, ce n'est pas le cas en C ou dans d'autres langages comme Java ou C#.
Raison du manque de covariance du modèle
L'absence de covariance du modèle est justifiée par le besoin de maintenir la sécurité du type. Prenons l'exemple suivant :
<code class="cpp">// Class hierarchy class Fruit {...}; class Apple : public Fruit {...}; class Orange : public Fruit {...}; // Template instantiation using std::vector int main() { std::vector<Apple> apple_vec; apple_vec.push_back(Apple()); // Valid // With covariance, the following would be allowed std::vector<Fruit>& fruit_vec = apple_vec; // Adding an Orange to the vector fruit_vec.push_back(Orange()); // Incorrect addition of an orange to an apple vector }</code>
Cela démontre le potentiel de comportement dangereux si les modèles étaient covariants. Par conséquent, T et T sont considérés comme des types complètement distincts, quelle que soit la relation entre A et B.
Résoudre le problème
Une approche pour résoudre le problème en Java et C# consiste à utiliser des types limités caractères génériques et contraintes, respectivement :
<code class="java">Bar(Container<? extends Interface) {...}
<code class="csharp">Bar<T>(Container<T> container) where T : Interface {...}</code>
En C , la bibliothèque Boost Concept Check peut fournir des fonctionnalités similaires. Cependant, l'utilisation d'une simple assertion statique peut être une solution plus pratique pour le problème spécifique rencontré :
<code class="cpp">static_assert(std::is_base_of<Interface, Foo>::value, "Container must hold objects of type Interface or its derived classes.");</code>
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!