IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage C++ Discussion :

BUG GCC ? "request for method is ambigous"


Sujet :

Langage C++

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Février 2006
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 13
    Points : 12
    Points
    12
    Par défaut BUG GCC ? "request for method is ambigous"
    Salut à tous,
    Le code suivant (test.cpp) ne compile pas avec gcc (gnu).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    struct A { int getValue()		{ return 33 ; } } ;
    struct B { int getValue( int i )	{ return i * 2 ; } } ;
    struct C : public A, B			{} ;
     
    int main( int, char *[] )
    	{
    	C c ;
    	c.getValue( 5 ) ;
    	}
    Voilà ce que donne la compilation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    test/test.cpp:11:4: error: request for member ‘getValue’ is ambiguous
      c.getValue( 5 ) ;
        ^
    test/test.cpp:5:16: note: candidates are: int B::getValue(int)
     struct B { int getValue( int i ) { return i * 2 ; } } ;
                    ^
    test/test.cpp:4:16: note:                 int A::getValue()
     struct A { int getValue()  { return 33 ; } } ;
    Ce n'est pas la première fois que je suis obligé de contourner le problème de la non-résolution d'un appel de méthode, par exemple en préfixant l'appel à la méthode non résolue par la classe propriétaire :

    Mais ce n'est pas réellement satisfaisant ni très joli.
    Sur internet je n'ai jamais trouvé de réponse, car les demandes sur ce problème portent en général sur des cas évidents.

    Est-ce un bug du compilateur ou ai-je loupé quelque chose ?
    Suis-je le seul à rencontrer ce problème ?
    Merci

  2. #2
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Hello,
    Citation Envoyé par fafax Voir le message
    Est-ce un bug du compilateur ou ai-je loupé quelque chose ?
    Suis-je le seul à rencontrer ce problème ?
    Merci
    Les cas un peu bizarre avec de l'héritage multiples je connais pas trop, mais vu que MSVC donne la même erreur je dirai que ça ne vient pas du compilo et que t'es obligé de préciser la base pour lever l’ambiguïté.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    1>main.cpp(13): error C2385: accès ambigu de 'getValue'
    1>  main.cpp(13): note: peut être le 'getValue' en base 'A'
    1>  main.cpp(13): note: ou peut être le 'getValue' en base 'B'
    1>main.cpp(13): error C2660: 'A::getValue'*: la fonction ne prend pas 1 arguments

  3. #3
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Bonjour,

    Le comportement est normal.

    Quand le compilateur cherche le nom f, uniquement le nom (on oublie tout le reste, pas de notion de signature ou d'accessibilité), il commence par regarder dans la définition du type de *this. Si il trouve très bien, sinon il procède de manière récursive sur les types de bases directe, i.e. il fait comme si le type de *this était un des types de base direct. Il fusionne ensuite les résultats, pour qu'il y ait fusion il faut qu'un résultat inclue l'autre (pour faire simple), sinon il y a ambiguïté.

    Dans ton exemple, il n'y a pas de getValue dans C donc il fait la recherche dans A et B, il trouve dans un cas A::getValue et dans l'autre B::getValue, puis vient la fusion, les deux résultats sont disjoints : ambiguité.

  4. #4
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Une façon simple de corriger ton code est de descendre les deux chaînes au niveau de C:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    struct C : public A, B 
    {
    	using A::getValue;
    	using B::getValue;
    };
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Février 2006
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 13
    Points : 12
    Points
    12
    Par défaut
    Quand le compilateur cherche le nom f, uniquement le nom (on oublie tout le reste, pas de notion de signature ou d'accessibilité), il commence par regarder dans la définition du type de *this.
    Merci de cette explication.
    Le polymorphisme n'est donc pas réalisé dans le contexte de l'héritage multiple.
    C'est un point que j'apprends.

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Février 2006
    Messages
    13
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 13
    Points : 12
    Points
    12
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    Une façon simple de corriger ton code est de descendre les deux chaînes au niveau de C:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    struct C : public A, B 
    {
    	using A::getValue;
    	using B::getValue;
    };
    Merci JolyLoic de cette solution, qui répond au problème en gardant l'élégance du polymorphisme

  7. #7
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Salut,
    Citation Envoyé par fafax Voir le message
    Merci de cette explication.
    Le polymorphisme n'est donc pas réalisé dans le contexte de l'héritage multiple.
    C'est un point que j'apprends.
    Si, le polymorphisme est totalement réalisé dans le cas de l'héritage multiple... Simplement il vient avec certaines restrictions qui sont tout à fait normales au demeurant : les fonctions des classes de bases (qu'elles soient virtuelles ou non) doivent être non ambigües.
    Ainsi, si tu as un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    class A{
    public:
        virtual void foo() const;
        /* ... */
    }
    void A::foo() const{
       std::cout<<"foo depuis un A\n";
    }
    class B{
    public:
        virtual void bar() const;
    };
    void B::bar() const{
        std::cout<<"bar depuis un B \n";
    }
    class C : public A, public B{
    public:
        void foo() const override;
        void bar() const override;
    }
    void C::foo() const{
        std::cout<<"foo depuis un C\n";
    }
    void C::bar() const{
        std::cout<<"bar depuis un C\n";
    }
    void truc(A const & a){
        a.foo();
    }
    void machin(B const & b){
        b.bar();
    }
    int main(){
        A a;
        B b;
        C c;
        truc(a); // OK : foo depuis un A
        truc(c); // OK : foo depuis un C
        machin(b); // OK : bar depuis un B
        machin(c); // OK : bar depuis un C
    }
    tu n'auras absolument aucun problème.

    Du moins, tant que tu n'essayeras pas d'appeler une fonction qui existerait à la fois dans A et dans B
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

Discussions similaires

  1. Envoie email: No overload for method
    Par kiwi645 dans le forum Windows Forms
    Réponses: 10
    Dernier message: 23/01/2008, 14h02
  2. Réponses: 14
    Dernier message: 14/09/2007, 17h28
  3. Request for heineheinessement
    Par gifffftane dans le forum NetBeans
    Réponses: 3
    Dernier message: 26/03/2007, 12h39
  4. [VBS]Bug sur les boucles for.
    Par méphistopheles dans le forum VBScript
    Réponses: 7
    Dernier message: 24/03/2006, 22h17

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo