Maison  >  Article  >  développement back-end  >  ## Pourquoi l'héritage multiple avec les classes de base de modèle provoque-t-il une ambiguïté dans la résolution des fonctions membres ?

## Pourquoi l'héritage multiple avec les classes de base de modèle provoque-t-il une ambiguïté dans la résolution des fonctions membres ?

Barbara Streisand
Barbara Streisandoriginal
2024-10-25 04:58:02530parcourir

## Why Does Multiple Inheritance with Template Base Classes Cause Ambiguity in Member Function Resolution?

Ambiguïté dans la levée de l'ambiguïté de l'héritage multiple

Lors du traitement de l'héritage multiple à l'aide de classes de base de modèles, un problème potentiel se pose concernant la résolution ambiguë des fonctions membres. Considérez le scénario suivant :

<code class="cpp">template <typename ... Types>
class Base {
public:
  template <typename T>
  typename std::enable_if<Contains<T, Types ...>::value>::type foo() {
    std::cout << "Base::foo()\n";
  }
};

Ici, la fonction foo() n'est appelable que lorsque le paramètre de modèle correspond à l'un des types du pack Types. Désormais, si une classe dérivée hérite de plusieurs classes de base avec des ensembles de types qui ne se chevauchent pas, le compilateur peut rencontrer une ambiguïté lors de la résolution de l'appel foo().

<code class="cpp">struct Derived: public Base<int, char>,
                public Base<double, void>
{};</code>

Dans ce cas, l'appel Derived(). foo() appellerait idéalement la fonction membre foo() de Base. Cependant, GCC et Clang signalent une ambiguïté.

Pourquoi le compilateur ne peut pas résoudre l'ambiguïté

L'erreur de compilation survient en raison des règles de fusion pour la recherche de fonctions membres. Selon le standard C, si la fonction membre n'est pas déclarée dans la classe dérivée elle-même, le processus de recherche recherche à son tour dans les classes de base. Cependant, si les ensembles de déclarations dans les classes de base diffèrent, la fusion devient ambiguë.

Dans le scénario donné, la classe dérivée Derived ne déclare pas explicitement foo(), le compilateur doit donc fusionner les ensembles de recherches du deux classes de base. Étant donné que les classes de base contiennent différents ensembles de déclarations pour foo(), la fusion entraîne une ambiguïté.

Solutions

Pour résoudre cette ambiguïté, une option consiste à utiliser des déclarations using dans la classe dérivée pour importer explicitement les fonctions membres souhaitées. Cependant, cela nécessite que l'utilisateur ajoute ces déclarations, ce qui peut être verbeux et peu pratique pour les grandes listes de types.

<code class="cpp">struct Derived: public Base<int, char>,
                public Base<double, void>
{
    using Base<int, char>::foo;
    using Base<double, void>::foo;
};</code>

Alternativement, on peut utiliser une classe d'assistance qui collecte et fusionne les fonctions membres de toutes les classes de base. , permettant à la classe dérivée d'y accéder directement.

<code class="cpp">template <typename... Bases>
struct BaseCollector : Bases...
{
  using Bases::foo...;
};

struct Derived : BaseCollector<Base<int, char>, Base<double, void>>
{};</code>

Avec cette approche, l'utilisateur n'a pas besoin d'ajouter de déclarations supplémentaires pour résoudre l'ambiguïté. La classe BaseCollector fusionne efficacement les ensembles de déclarations de toutes les classes de base, rendant la fonction foo() disponible pour la classe dérivée sans ambiguïté.

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