Maison >développement back-end >C++ >Pourquoi C ne prend-il pas en charge la covariance des modèles et comment pouvons-nous résoudre les problèmes de sécurité des types qui en résultent lorsque nous travaillons avec des modèles polymorphes ?

Pourquoi C ne prend-il pas en charge la covariance des modèles et comment pouvons-nous résoudre les problèmes de sécurité des types qui en résultent lorsque nous travaillons avec des modèles polymorphes ?

Patricia Arquette
Patricia Arquetteoriginal
2024-10-28 08:14:02611parcourir

Why doesn't C   support template covariance, and how can we address the resulting type safety issues when working with polymorphic templates?

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn