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 :

Problème de multiple définition


Sujet :

C++

  1. #1
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Janvier 2013
    Messages
    2
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2013
    Messages : 2
    Points : 1
    Points
    1
    Par défaut Problème de multiple définition
    Bonjour,
    Je suis nouveau ici et je viens requerir de l'aide.
    Voilà je sais que mon problème tourne autour de la définition d'objet static, mais cela fait maintenant 2h que je cherche sans succès une réponse.

    voici mon fichier EtatRobot.h
    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
    #ifndef _ETATROBOT_H_
    #define _ETATROBOT_H_
     
    #include <string>
    #include <map>
    #include "Robot.h"
     
    using namespace std;
     
    class Robot;
     
    class EtatRobot {
        public:
            EtatRobot(string nomEtat): _nomEtat(nomEtat){}
            virtual void avancer(int x,int y){throw BadStateException();}
            virtual void tourner(string direction){throw BadStateException();}
            virtual void saisir(Objet o){throw BadStateException();}
            virtual void poser(){throw BadStateException();}
            virtual int peser(){throw BadStateException();}
            virtual void rencontrerObstacle(Obstacle o){throw BadStateException();}
            virtual int evaluerObstacle(){throw BadStateException();}
            virtual void figer(){throw BadStateException();}
            virtual void repartir(){throw BadStateException();}
            string getNomEtat(){ return _nomEtat;}
            Robot* getRobot(){ return _robot;}
     
            static map<string,EtatRobot*> _mapEtats; 
     
            class BadStateException{};
     
        protected:
            /* data */
            string _nomEtat;
            Robot* _robot;
     
    }; /* EtatRobot */
     
    #endif /* end of include guard: _ETATROBOT_H_ */
    Ici le .cpp
    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
    #include "EtatRobot.h"
    #include "EtatAVide.h"
    #include "EtatAVideFaceObstacle.h"
    #include "EtatEnCharge.h"
    #include "EtatEnChargeFaceObstacle.h"
    #include "EtatFige.h"
    #include "Robot.h"
     
     
    map<string,EtatRobot*> EtatRobot::_mapEtats;
    EtatAVide EtatAVide::eav("VIDE");
    EtatAVideFaceObstacle EtatAVideFaceObstacle::eavfo("AVIDEOBS");
    EtatEnCharge EtatEnCharge::eec("ENCHARGE");
    EtatEnChargeFaceObstacle EtatEnChargeFaceObstacle::eecfo("ENCHARGEOBS");
    EtatFige EtatFige::ef("FIGE");
    Et après j'ai des états qui dérive de EtatRobot avec une variable static style eav pour EtatAVide.

    Les erreurs sont :
    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
    EtatRobot.o:(.bss+0x0): multiple definition of `EtatRobot::_mapEtats'
    EtatRobot.o:(.bss+0x0): first defined here
    EtatRobot.o:(.bss+0x30): multiple definition of `EtatAVide::eav'
    EtatRobot.o:(.bss+0x30): first defined here
    EtatRobot.o:(.bss+0x50): multiple definition of `EtatAVideFaceObstacle::eavfo'
    EtatRobot.o:(.bss+0x50): first defined here
    EtatRobot.o:(.bss+0x70): multiple definition of `EtatEnCharge::eec'
    EtatRobot.o:(.bss+0x70): first defined here
    EtatRobot.o:(.bss+0x90): multiple definition of `EtatEnChargeFaceObstacle::eecfo'
    EtatRobot.o:(.bss+0x90): first defined here
    EtatRobot.o:(.bss+0xc0): multiple definition of `EtatFige::ef'
    EtatRobot.o:(.bss+0xc0): first defined here
    main.o: In function `main':
    main.cpp:(.text+0x18): undefined reference to `Robot::Robot()'
    EtatRobot.o: In function `EtatFige::repartir()':
    EtatRobot.cpp:(.text._ZN8EtatFige8repartirEv[EtatFige::repartir()]+0x23): undefined reference to `Robot::changeEtat(EtatRobot*)'
    EtatEnRoute.o: In function `EtatEnRoute::figer()':
    EtatEnRoute.cpp:(.text+0xad): undefined reference to `Robot::changeEtat(EtatRobot*)'
    EtatEnCharge.o: In function `EtatEnCharge::rencontrerObstacle(Obstacle&)':
    EtatEnCharge.cpp:(.text+0x23): undefined reference to `Robot::changeObs(Obstacle)'
    EtatEnCharge.cpp:(.text+0x6b): undefined reference to `Robot::changeEtat(EtatRobot*)'
    EtatEnCharge.o: In function `EtatEnCharge::peser()':
    EtatEnCharge.cpp:(.text+0xd2): undefined reference to `Robot::getObjet()'
    EtatEnCharge.o: In function `EtatEnCharge::avancer(int, int)':
    EtatEnCharge.cpp:(.text+0x10e): undefined reference to `Robot::changePos(int, int)'
    EtatEnCharge.o: In function `EtatEnCharge::tourner(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
    EtatEnCharge.cpp:(.text+0x14b): undefined reference to `Robot::changeDir(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
    EtatEnChargeFaceObstacle.o: In function `EtatEnChargeFaceObstacle::poser()':
    EtatEnChargeFaceObstacle.cpp:(.text+0x37): undefined reference to `Robot::changeObj(Objet)'
    EtatEnChargeFaceObstacle.cpp:(.text+0x7f): undefined reference to `Robot::changeEtat(EtatRobot*)'
    EtatEnChargeFaceObstacle.o: In function `EtatEnChargeFaceObstacle::peser()':
    EtatEnChargeFaceObstacle.cpp:(.text+0xfe): undefined reference to `Robot::getObjet()'
    EtatEnChargeFaceObstacle.o: In function `EtatEnChargeFaceObstacle::tourner(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
    EtatEnChargeFaceObstacle.cpp:(.text+0x14b): undefined reference to `Robot::changeDir(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
    EtatEnChargeFaceObstacle.cpp:(.text+0x19f): undefined reference to `Robot::changeEtat(EtatRobot*)'
    EtatAVide.o: In function `EtatAVide::rencontrerObstacle(Obstacle&)':
    EtatAVide.cpp:(.text+0x23): undefined reference to `Robot::changeObs(Obstacle)'
    EtatAVide.cpp:(.text+0x6b): undefined reference to `Robot::changeEtat(EtatRobot*)'
    EtatAVide.o: In function `EtatAVide::tourner(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
    EtatAVide.cpp:(.text+0xf1): undefined reference to `Robot::changeDir(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
    EtatAVide.o: In function `EtatAVide::avancer(int, int)':
    EtatAVide.cpp:(.text+0x148): undefined reference to `Robot::changePos(int, int)'
    EtatAVideFaceObstacle.o: In function `EtatAVideFaceObstacle::evaluerObstacle()':
    EtatAVideFaceObstacle.cpp:(.text+0x18): undefined reference to `Robot::getObstacle()'
    EtatAVideFaceObstacle.o: In function `EtatAVideFaceObstacle::tourner(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
    EtatAVideFaceObstacle.cpp:(.text+0x65): undefined reference to `Robot::changeDir(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
    EtatAVideFaceObstacle.cpp:(.text+0xb9): undefined reference to `Robot::changeEtat(EtatRobot*)'
    EtatAVideFaceObstacle.o: In function `EtatAVideFaceObstacle::saisir(Objet&)':
    EtatAVideFaceObstacle.cpp:(.text+0x145): undefined reference to `Robot::changeObj(Objet)'
    EtatAVideFaceObstacle.cpp:(.text+0x18d): undefined reference to `Robot::changeEtat(EtatRobot*)'
    collect2: ld a retourné 1 code d'état d'exécution
    make: *** [main] Erreur 1
    Merci beaucoup pour votre aider.

  2. #2
    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,

    Apparemment, tu as un problème avec les membres statiques, hein

    Essayes un peu
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    map<string,EtatRobot*> EtatRobot::_mapEtats = map<string,EtatRobot*> ;
    EtatAVide EtatAVide::eav = EtatAVide("VIDE");
    EtatAVideFaceObstacle EtatAVideFaceObstacle::eavfo = EtatAVideFaceObstacle("AVIDEOBS");
    EtatEnCharge EtatEnCharge::eec = EtatEnCharge("ENCHARGE");
    EtatEnChargeFaceObstacle EtatEnChargeFaceObstacle::eecfo =EtatEnChargeFaceObstacle("ENCHARGEOBS");
    EtatFige EtatFige::ef = EtatFige("FIGE");
    Ceci dit, je ne saurais trop te conseiller de choisir un peu mieux le nom de tes variables...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    eav   -> etatAVide
    eavfo -> etatAVideFaceObstacle
    eec   -> etatEnCharge
    ef    -> etatFige
    seraient, à mon sens, beaucoup plus clairs à l'utilisation, et pas plus fatiguant à écrire
    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

  3. #3
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 113
    Points : 32 960
    Points
    32 960
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    utilises-tu un IDE ? Comment compiles-tu ?
    Tu n 'as pas un include de cpp tout de même ?
    Où sont déclarés les autres objets static ? eav etc ?

    Par contre, inutile de construire ta map static dans le .cpp puisque tu utilises le constructeur par défaut, qui est déjà appelé automatiquement
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  4. #4
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Janvier 2013
    Messages
    2
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2013
    Messages : 2
    Points : 1
    Points
    1
    Par défaut
    Bonjour,
    Je compile avec un makefile sans IDE. J'ai vérifié mes includes et tout est bon, j'avais eu des problèmes avec les doubles inclusions, mais je pense pas que ça soit encore ça.
    Les autres objets statiques sont déclaré dans leurs classe respective.
    Je vais essayé la solution de koala01 et je vous tiens au courant.

  5. #5
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 113
    Points : 32 960
    Points
    32 960
    Billets dans le blog
    4
    Par défaut
    On dirait que tu link plusieurs fois le .cpp
    Peux-tu montrer le makefile ?
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  6. #6
    Membre à l'essai
    Homme Profil pro
    Ingénieur télécom
    Inscrit en
    Février 2011
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur télécom

    Informations forums :
    Inscription : Février 2011
    Messages : 6
    Points : 12
    Points
    12
    Par défaut
    Citation Envoyé par Bousk Voir le message
    On dirait que tu link plusieurs fois le .cpp
    Peux-tu montrer le makefile ?
    Le problème doit venir de la mais c'est bizare quand même.
    Par hasard tu ne ferais pas
    • .o pour le .cpp et .h
    • ensuite le main avec main.cpp etatrobot.cpp
    • tu link le tout ensemble

    Sinon ça ne semble pas être le cas mais tu n'utiliserais pas deux compilateurs différents pour générer ton code non plus?
    Typiquement tu link du code C et C++ qui inclus le même .h contenant des membres statiques?

    La visiblement ce n'est pas le cas mais j'ai déjà eu ce problème avec g++ et nvcc!!

  7. #7
    Membre éprouvé
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2009
    Messages
    552
    Détails du profil
    Informations personnelles :
    Localisation : France

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

    Informations forums :
    Inscription : Mars 2009
    Messages : 552
    Points : 1 060
    Points
    1 060
    Par défaut
    Bonsoir,

    Hihihi, c'est plus bête que ça non? Des méthodes définies dans les .h et incluent dans des .cpp différents => deux fois les codes objets?

    Dans EtatRobot.h, il faudrait virer dans le .cpp toutes les implémentations
    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
     
    class EtatRobot {
        public:
            EtatRobot(string nomEtat) ;
            virtual void avancer(int x,int y) ;
            //idem pour les autres...
     
            static map<string,EtatRobot*> _mapEtats; 
     
            class BadStateException{};
     
        protected:
            /* data */
            string _nomEtat;
            Robot* _robot;
     
    }; /* EtatRobot */
    EtatRobot.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    //initialisation de la statique
    map<string,EtatRobot*> EtatRobot::_mapEtats; 
     
    //...
    EtatRobot::EtatRobot(string nomEtat): _nomEtat(nomEtat){}
    void EtatRobot::avancer(int x,int y){throw BadStateException();}
    //idem pour les autres...
     
    //...
    A moins que les méthodes/fonctions soient inline ou templatée, il faut les mettre dans des .cpp (le compilo doit leurs réserver un traitement particulier pour éviter ces définitions multiples)

  8. #8
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 113
    Points : 32 960
    Points
    32 960
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par bretus Voir le message
    Hihihi, c'est plus bête que ça non? Des méthodes définies dans les .h et incluent dans des .cpp différents => deux fois les codes objets?
    Les méthodes implémentées dans la déclaration d'une classe sont automatiquement inline. A moins qu'il existe et qu'il utilise un compilateur particulier qui définit sa propre tambouille à ce sujet..? Ce point ne devrait pas gêner.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  9. #9
    Membre éprouvé
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2009
    Messages
    552
    Détails du profil
    Informations personnelles :
    Localisation : France

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

    Informations forums :
    Inscription : Mars 2009
    Messages : 552
    Points : 1 060
    Points
    1 060
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Les méthodes implémentées dans la déclaration d'une classe sont automatiquement inline. A moins qu'il existe et qu'il utilise un compilateur particulier qui définit sa propre tambouille à ce sujet..? Ce point ne devrait pas gêner.
    Tu m'en apprends une là...

    J'ai déjà eu des soucis avec ce genre de chose et même avec des spécialisations de template (de mémoire dans Visual Studio 2008) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    template < typename T >
    void print( const T& v ){
            // OK dans header
    }
     
    template <>
    void print( const double& v ){
            // Pose des problèmes de définition multiple
    }
    EDIT : J'ai vérifié tes dire sous gcc 4.6.3, effectivement, pas de souci (reboot)

  10. #10
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 113
    Points : 32 960
    Points
    32 960
    Billets dans le blog
    4
    Par défaut
    Les templates doivent obligatoirement être dans le header pourtant, peut-être avais-tu un problème de guard include ? Auquel cas le problème de multiple definition intervient à la compilation et non au linker il me semble (et sont de l'ordre du "already defined" là où on a du "multiple definition").
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  11. #11
    Membre éprouvé
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2009
    Messages
    552
    Détails du profil
    Informations personnelles :
    Localisation : France

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

    Informations forums :
    Inscription : Mars 2009
    Messages : 552
    Points : 1 060
    Points
    1 060
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Les templates doivent obligatoirement être dans le header pourtant, peut-être avais-tu un problème de guard include ? Auquel cas le problème de multiple definition intervient à la compilation et non au linker il me semble (et sont de l'ordre du "already defined" là où on a du "multiple definition").
    Les template oui, mais les spécialisations peuvent ne plus avoir de paramètre template.

    J'ai mémoire de me ramasser des erreurs de link du type "multiple definition" sur des programmes qui compilent tranquillement sous GCC.

    Là malgré un fastidieux reboot, je n'arrive pas à reproduire (visual 2010 express)... Ça m'intrigue, je testerai avec le 2008.

    Désolé pour la fausse piste
    ++

Discussions similaires

  1. comment résoudre un problème de multiple définition
    Par razily dans le forum Débuter
    Réponses: 8
    Dernier message: 24/03/2010, 19h29
  2. Réponses: 19
    Dernier message: 05/01/2008, 16h06
  3. [FLASH MX] Problème onPress multiple
    Par abenhass dans le forum ActionScript 1 & ActionScript 2
    Réponses: 3
    Dernier message: 14/04/2006, 09h25
  4. [ActiveX Acrobat] Problème avec la définition du CLSID / EVENTID
    Par SubZero2 dans le forum API, COM et SDKs
    Réponses: 10
    Dernier message: 19/09/2005, 08h54
  5. [KeyEvent] Problème de multiples appels
    Par pierre.zelb dans le forum AWT/Swing
    Réponses: 13
    Dernier message: 11/08/2005, 14h53

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