Maison >développement back-end >C++ >## Comment lever l'ambiguïté des appels de membres de classe dans un héritage multiple avec des ensembles de types qui se chevauchent ?

## Comment lever l'ambiguïté des appels de membres de classe dans un héritage multiple avec des ensembles de types qui se chevauchent ?

Susan Sarandon
Susan Sarandonoriginal
2024-10-25 06:03:02656parcourir

## How to Disambiguate Class Member Calls in Multiple Inheritance with Overlapping Type Sets?

Désambiguïsation d'un membre de classe dans un héritage multiple avec des ensembles qui se chevauchent

En C, l'héritage multiple avec des ensembles de types qui se chevauchent peut conduire à une ambiguïté lors de l'appel fonctions membres avec des paramètres de modèle. Pour comprendre pourquoi, examinons un modèle de classe de base :

<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";
    }
};

Le membre foo() ne peut être appelé que lorsque le paramètre de modèle spécifié est présent dans la liste des paramètres de modèle de Base. Supposons maintenant que nous définissions une classe dérivée Derived qui hérite de plusieurs instances de Base avec des ensembles de types qui ne se chevauchent pas :

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

Lors de l'appel de Derived().foo(), le compilateur pourrait ne pas être capable de déterminer quelle classe de base utiliser car le paramètre de modèle int est présent dans les deux classes de base. Cette ambiguïté entraînerait une erreur du compilateur.

Solutions possibles

  1. Spécification de base explicite : L'ambiguïté peut être résolue en spécifiant explicitement la classe de base à utiliser, par exemple, Derived().Base::foo(). Cependant, cette solution nécessite que l'appelant connaisse la classe de base spécifique, ce qui peut être indésirable.
  2. Utilisation de déclarations : En C , l'utilisation de déclarations peut amener les membres des classes de base dans l'espace de noms du classe dérivée. En ajoutant using Base::foo; et en utilisant Base::foo; à la déclaration de classe dérivée, l’ambiguïté peut être levée. Cependant, cette solution nécessite que l'utilisateur de la classe dérivée les inclue à l'aide de déclarations, ce qui peut être fastidieux et répétitif pour les grandes listes de types.
  3. Modèle de classe de collecteur de base : Une solution plus élégante est pour employer un modèle de classe de collecteur qui combine les déclarations de toutes les classes de base et expose les membres via l'utilisation de déclarations. Par exemple :
<code class="cpp">template <typename... Bases>
struct BaseCollector;

template <typename Base>
struct BaseCollector<Base> : Base
{
    using Base::foo;
};

template <typename Base, typename... Bases>
struct BaseCollector<Base, Bases...>:
    Base,
    BaseCollector<Bases...>
{
    using Base::foo;
    using BaseCollector<Bases...>::foo;
};

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

Cette approche permet à la classe dérivée d'accéder à l'implémentation correcte de la classe de base sans avoir besoin de déclarations explicites d'utilisation ou de spécification de classe de base.

Comprendre l'ambiguïté et la mise en œuvre de solutions efficaces dans l'héritage multiple avec des ensembles qui se chevauchent permet de garantir une exécution de code claire et correcte.

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