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

 C++ Discussion :

Erreur de compilation : call of overloaded- is ambiguous


Sujet :

C++

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2015
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2015
    Messages : 23
    Points : 19
    Points
    19
    Par défaut Erreur de compilation : call of overloaded- is ambiguous
    Bonjour,

    Je travaille sur un projet étudiant de casse brique. Et je souhaite trouver avec quelle forme ma balle rentre en collision.
    J'ai un problème lié à la gestion de mon pointeur de classe.

    Mon problème repose sur trois classes : forme, murbrique, raquette.
    Murbrique et raquette héritent tous les deux de forme.
    J'ai une classe qui listent les formes qui sont instanciées et par le biais d'une méthode selection(x,y) je récupère dans un pointeur (de type forme *) l'adresse de la forme qui se trouve aux coordonnées (x,y)
    Je souhaite effectué un traitement différent en fonction du type de forme contenu dans ce pointeur.

    J'ai donc deux méthodes détection qui prennent deux types de paramètre différents, qui effectuent donc mes traitements distincts.

    Le compilateur m'affiche "error: call of overloaded 'detection(forme*&)' is ambiguous"

    J'aimerais donc que mon pointeur de forme se "spécialise" en fonction de l'objet sur lequel il pointe et qu'ainsi il sache quelle méthode utiliser.

    Voici le code :
    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
    void balle::collision(listeforme liste)
    {
        float x,y;
        forme * pforme;
        x= p.getx();
        y= p.gety();
        pforme = liste.selection(x,y);
        if((pforme!=this)&&(pforme!=NULL))
        {
            detection(pforme);
        }
     
        //Collision avec l'écran
        if((y<=0)||(y>=SCREEN_H))
            rebond(true);
        if((x<=0)||(x>=SCREEN_W))
            rebond(false);
    }
     
     
    void balle::detection(murbrique* pm)
    {
        //traitement 1
    }
    void balle::detection(raquette* praq)
    {
        //traitement 2
    }

    Je vous remercie par avance de votre aide.

  2. #2
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 586
    Points : 7 724
    Points
    7 724
    Par défaut
    Bonjour,

    La spécialisation d'un paramètre est toujours statique.
    Pour avoir une résolution dynamique, le seul moyen est l'utilisation d'une fonction virtuelle.
    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
    class forme {
    public:
       virtual bool detection( class balle* )const = 0;
    };
    class murbrique : public forme {
        bool detection( class balle* )const override;
    };
    class raquette : public forme {
        bool detection( class balle* )const override;
    };
    void balle::collision( listeforme liste ) {
        forme* pforme = liste.selection( p.getx(), p.gety() );
        if ( pforme != this  &&  pforme ) {
            pforme->detection( this );
        }
    }
    bool murbrique::detection( balle* pba )const {
        //traitement 1
    }
    bool raquette::detection( balle* pba )const {
        //traitement 2
    }

  3. #3
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2015
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2015
    Messages : 23
    Points : 19
    Points
    19
    Par défaut
    Bonjour,

    C'est bien ce que je pensais.

    Merci beaucoup pour votre réponse limpide.

    Bon week-end.

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 131
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 131
    Points : 33 074
    Points
    33 074
    Billets dans le blog
    4
    Par défaut
    Salut,

    void balle::collision(listeforme liste) liste est passée par copie, liste.selection(x,y); retourne un pointeur.
    - comment sont gérés les données internes ?
    Si la copie détruit les données, tu auras un problème à la sortie de ta fonction sur les données initiales.
    Si elle ne les détruit pas, je pense que tu as une fuite mémoire qui traine. A moins que tu aies mis en place un système de référence ou quelque chose qui finisse par les supprimer ?

  5. #5
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2015
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2015
    Messages : 23
    Points : 19
    Points
    19
    Par défaut
    Bonjour,

    Ma classe listeforme est déclarée comme suit :

    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
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
     
    class listeforme
    {
        public:
            listeforme();
            ~listeforme();
            void ajoute(forme*);
            void supprime(forme*);
            void affiche();
            forme* selection(int,int);
     
        protected:
            list<forme*> l;
            list<forme*>::iterator it;
     
        private:
    };
     
    listeforme::listeforme()
    {
        //ctor
    }
     
    listeforme::~listeforme()
    {
        //dtor
    }
    void listeforme::ajoute(forme* p)
    {
        l.push_back(p);
    }
     
    void listeforme::supprime(forme* p)
    {
        l.remove(p);
    }
     
    void listeforme::affiche()
    {
        for(it = l.begin(); it != l.end() ; it++)
        {
            (*it)->affiche();
        }
    }
     
    forme* listeforme::selection(int sx, int sy)
    {
        for(it = l.begin() ; it != l.end() ; it++)
        {
            if((*it)->selection(sx,sy))
                return(*it);
        }
        return NULL;
    }
    La liste est déclarée statique dans la classe forme. A chaque fois qu'une forme est ajoutée, son constructeur appelle la méthode ajoute qui ajoute à la liste un référencement.
    A chaque fois qu'une forme est détruite, son destructeur appelle la méthode supprime. Donc normalement il n'y a aucune fuite mémoire de ce côté, étant donné que je n'influence pas le référencement manuellement. Il s'effectue de manière automatique lors que l'instanciation ou de la destruction de la forme. (dans mon main j'instancie des formes de manière statique)
    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
    class forme
    {
        public:
            forme();
            virtual ~forme();
            virtual void affiche()=0;
            virtual bool selection(int,int)=0;
            virtual void collision(balle*,int)=0;
            static listeforme& gett();
            void bloque();
            void debloque();
        protected:
            static listeforme t;
            static bool blck;
        private:
    };
    listeforme forme::t;
    bool forme::blck=false;
    forme::forme()
    {
        if(!blck)
            t.ajoute(this);
    }
    forme::~forme()
    {
        t.supprime(this);
    }
    J'avoue que copier la listeforme n'est pas une très bonne idée niveau optimisation. J'ai tenté de modifier le type de paramètre en "const listeforme &" mais le compilateur me signale une erreur lors de l'appel de liste.selection(x,y)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    error: passing 'const listeforme' as 'this' argument of 'forme* listeforme::selection(int, int)' discards qualifiers [-fpermissive]
    Etant encore débutant, je ne sais pas ce qu'implique vraiment le fait de déclarer mon paramètre en tant que "const listeforme &". Tel que je le vois (est ce que je me trompe ?), "listeforme &" permet de passer une référence, qui donne accès en écriture sur la liste (ce que je ne souhaite pas) et const précise que ce paramètre n'est plus accessible en écriture.
    Néanmoins je ne sais absolument pas ce que ça implique sur l'appel de méthode de cette classe.

    Merci d'avance pour vos réponses

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 131
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 131
    Points : 33 074
    Points
    33 074
    Billets dans le blog
    4
    Par défaut
    En gros ta liste est statique et chaque élément d'y enregistre à la construction, et désenregistre à la destruction j'espère. Si tous les éléments sont correctement détruits, tu ne devrais donc pas avoir de fuite.
    Ca reste bof mais possible, typiquement dans une classe de type manager où chaque élément s'enregistre à sa construction par exemple.
    Le problème se pose si tu copies la liste et enlève un élément : ta copie a un pointeur fucké et y accéder entraînera un comportement indéterminé, sûrement un crash.
    Copier des éléments c'est une opération. Ca peut être long et lourd. Le passage par référence est préféré. const référence si la lecture seule de l'élément suffit.
    Tu devrais toujours passer par const& tes éléments, sauf s'il s'agit d'un objet de base du langage (int, char, ...). S'il s'agit d'une structure type POD dont la taille est plus petite qu'à disons sizeof uint64 ou uint128, la copie peut également être meilleure, mais ce n'est généralement pas ce qu'on utilise quand on débute, on a des structures plus complexes, généralement des classes uniquement.

  7. #7
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2015
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2015
    Messages : 23
    Points : 19
    Points
    19
    Par défaut
    Citation Envoyé par Bousk Voir le message
    En gros ta liste est statique et chaque élément d'y enregistre à la construction, et désenregistre à la destruction j'espère. Si tous les éléments sont correctement détruits, tu ne devrais donc pas avoir de fuite.
    Ca reste bof mais possible, typiquement dans une classe de type manager où chaque élément s'enregistre à sa construction par exemple.
    Le problème se pose si tu copies la liste et enlève un élément : ta copie a un pointeur fucké et y accéder entraînera un comportement indéterminé, sûrement un crash.
    Copier des éléments c'est une opération. Ca peut être long et lourd. Le passage par référence est préféré. const référence si la lecture seule de l'élément suffit.
    Tu devrais toujours passer par const& tes éléments, sauf s'il s'agit d'un objet de base du langage (int, char, ...). S'il s'agit d'une structure type POD dont la taille est plus petite qu'à disons sizeof uint64 ou uint128, la copie peut également être meilleure, mais ce n'est généralement pas ce qu'on utilise quand on débute, on a des structures plus complexes, généralement des classes uniquement.
    D'accord je comprends mieux. Ce qui me sauve actuellement c'est que ma copie de liste est utilisée uniquement pour checker une seule forme. Le problème c'est qu'étant donné que ma méthode est appelée à chaque itération de la boucle qui gère mon programme, c'est lourd pour rien de passer une copie en paramètre à chaque itération. Je préfèrerais donc utiliser la " référence constante "

    Mais comment puis-je alors utiliser mes méthodes sur cette liste passée en "const listeforme&" ?
    Dois-je modifier la déclaration de ma méthode selection ? Parce qu'actuellement je n'arrive plus à l'utiliser (elle fonctionne lorsque je copie ma listeforme mais le compilateur me met l'erreur que j'ai mis dans mon post précédent.

  8. #8
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 586
    Points : 7 724
    Points
    7 724
    Par défaut
    Sur les 4 méthodes de listeforme, 2 sont sont prévues pour modifier l'objet listeforme, les 2 autres ne sont que de la consultation. Il faut déclarer affiche() et selection() en const, ainsi elles pourront être utilisées pour les listeforme const&.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class listeforme
    {
        public:
            void ajoute(forme*);             // inapplicable à un objet constant
            void supprime(forme*);           // inapplicable à un objet constant
            void affiche() const;            // ne modifie pas l'objet
            forme* selection(int,int) const; // ne modifie pas l'objet
    };

  9. #9
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2015
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2015
    Messages : 23
    Points : 19
    Points
    19
    Par défaut
    Citation Envoyé par dalfab Voir le message
    Sur les 4 méthodes de listeforme, 2 sont sont prévues pour modifier l'objet listeforme, les 2 autres ne sont que de la consultation. Il faut déclarer affiche() et selection() en const, ainsi elles pourront être utilisées pour les listeforme const&.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class listeforme
    {
        public:
            void ajoute(forme*);             // inapplicable à un objet constant
            void supprime(forme*);           // inapplicable à un objet constant
            void affiche() const;            // ne modifie pas l'objet
            forme* selection(int,int) const; // ne modifie pas l'objet
    };
    Merci infiniment pour vos conseils je vais tester tout ça.

  10. #10
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2015
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2015
    Messages : 23
    Points : 19
    Points
    19
    Par défaut
    J'ai essayé finalement de passer ma listeforme par référence, après avoir mis les méthodes affiche et selection en const. Maintenant c'est mes iterator qui posent problème. J'ai cherché sur stackoverflow, ils disent d'utiliser un const_iterator mais ça ne change rien, j'ai toujours une erreur.

    Je vous mets le code qui pose soucis :

    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
    class listeforme
    {
        public:
            listeforme();
            ~listeforme();
            void ajoute(forme*);
            void supprime(forme*);
            void affiche() const;
            forme* selection(int,int) const;
     
        protected:
            list<forme*> l;
            list<forme*>::const_iterator it;
     
        private:
    };
     
    void listeforme::affiche() const
    {
        for(it = l.begin(); it != l.end() ; ++it)
        {
            (*it)->affiche();
        }
    }
    Il détecte une erreur à la ligne du "for(it = l.begin(); it != l.end() ; ++it)"
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    error: passing 'const const_iterator {aka const std::_List_const_iterator<forme*>}' as 'this' argument of 'std::_List_const_iterator<forme*>& std::_List_const_iterator<forme*>::operator=(const std::_List_const_iterator<forme*>&)' discards qualifiers [-fpermissive]
    Désolé de vous importuner davantage, j'essaie de comprendre les tenants et les aboutissants du passage par référence

  11. #11
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 586
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 586
    Points : 7 724
    Points
    7 724
    Par défaut
    La fonction affiche() ne devrait pas modifier l'objet. Or pour itérer tu utilises un itérateur défini dans l'objet; lors de l'itération il doit changer successivement de valeur ce qui est en contradiction avec le fait que l'objet ne change pas.
    Alors, pourquoi avoir un itérateur dans l'objet? N'est-il pas plus logique d'utiliser une donnée locale pour itérer et de supprimer ce champ it de listeforme?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void listeforme::affiche() const {
        for ( std::list<forme*>::const_iterator it = l.cbegin() ; it != l.cend() ; ++it ) {
            (*it)->affiche();
        }
    }
    Mais cela peut aussi s'écrire plus simplement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void listeforme::affiche() const {
        for ( auto const& item : l ) { // pour tous les elements de la liste
            item->affiche();
        }
    }

  12. #12
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 131
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 131
    Points : 33 074
    Points
    33 074
    Billets dans le blog
    4
    Par défaut
    - it n'a rien à faire comme membre de ta classe
    - Il faut aussi changer les interfaces de forme pour qu'elle soit const-correct
    - si la fonction est const, le const sera implicite avec auto dans for ( auto& item : l )

  13. #13
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2015
    Messages
    23
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 27
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Février 2015
    Messages : 23
    Points : 19
    Points
    19
    Par défaut
    Je comprends un peu mieux le pourquoi du comment des incompréhensions du compilateur
    Il me reste encore pas mal de boulot alors pour coder proprement mon casse brique.

    Je vous remercie infiniment pour vos réponses, qui m'aident vraiment à comprendre le fond du fonctionnement du langage C++.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [XL-2003] "Erreur de compilation, nom ambigu détecté worksheet change". :/
    Par Imperium dans le forum Macros et VBA Excel
    Réponses: 8
    Dernier message: 23/09/2021, 15h36
  2. Réponses: 4
    Dernier message: 13/11/2013, 13h22
  3. Réponses: 3
    Dernier message: 25/10/2008, 16h06
  4. Réponses: 4
    Dernier message: 17/11/2007, 11h10
  5. Réponses: 21
    Dernier message: 06/05/2007, 12h49

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