"Si un ouvrier veut bien faire son travail, il doit d'abord affûter ses outils." - Confucius, "Les Entretiens de Confucius. Lu Linggong"
Page de garde > La programmation > ## 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 ?

Publié le 2024-11-08
Parcourir:455

## 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

Lorsque l'on traite 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 :

template 
class Base {
public:
  template 
  typename std::enable_if::value>::type foo() {
    std::cout 

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 jeux de types qui ne se chevauchent pas, le compilateur peut rencontrer une ambiguïté lors de la résolution de l'appel foo().

struct Derived: public Base,
                public Base
{};

Dans ce cas, l'appel Derived().foo() appellerait idéalement la fonction membre foo() depuis 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 les 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, qui peuvent être verbeuses et peu pratiques pour les grandes listes de types.

struct Derived: public Base,
                public Base
{
    using Base::foo;
    using Base::foo;
};

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.

template 
struct BaseCollector : Bases...
{
  using Bases::foo...;
};

struct Derived : BaseCollector, Base>
{};

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é.

Dernier tutoriel Plus>

Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.

Copyright© 2022 湘ICP备2022001581号-3