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 :

Undefined reference to une classe qui n'existe pas


Sujet :

Langage C++

  1. #1
    Invité
    Invité(e)
    Par défaut Undefined reference to une classe qui n'existe pas
    Bonjour, ou bonsoir

    Voila, je bosse actuellement sur un petit projet de jeux vidéo, et j'ai un soucis :

    J'ai une architecture de classe qui est faite de façon à être le plus modulaire possible :
    J'ai notamment la classe "MessageBox", qui est une classe abstraite qui donne la possibilité aux objets de communiquer entre eux, du genre :

    La classe IObject hérite de MessageBox, mais aussi la classe Listener, qui récupère les entrées utilisateurs

    Donc la classe GraphicsEngine est une classe qui hérite de la classe Engine, qui hérite de IObject.

    Voila le problème : tout compile parfaitement, mais au moment du linkage, il y a une erreur parlant de la classe "MessageBoxA". Or, cette classe n'existe tout simplement pas...

    Les erreurs se situent dans le fichier GraphicsEngine.o, et les voici :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    ||=== Build: Debug in JV (compiler: GNU GCC Compiler) ===|
    obj\Debug\Sources\Engine\GraphicsEngine.o:GraphicsEngine.cpp:(.rdata$_ZTV14GraphicsEngine[__ZTV14GraphicsEngine]+0x10)||undefined reference to `MessageBoxA::send_message(MessageBoxA*, Message&)'|
    obj\Debug\Sources\Engine\GraphicsEngine.o:GraphicsEngine.cpp:(.rdata$_ZTV14GraphicsEngine[__ZTV14GraphicsEngine]+0x14)||undefined reference to `MessageBoxA::receive_message(Message&)'|
    obj\Debug\Sources\Engine\GraphicsEngine.o:GraphicsEngine.cpp:(.rdata$_ZTV14GraphicsEngine[__ZTV14GraphicsEngine]+0x18)||undefined reference to `MessageBoxA::process_queue()'|
    ||=== Build failed: 3 error(s), 0 warning(s) (0 minute(s), 22 second(s)) ===|
    Voici le code de ma classe MessageBox :
    .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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
     
    #ifndef MESSAGEBOX_H
    #define MESSAGEBOX_H
     
    #include <string>
    #include <boost/serialization/serialization.hpp>
    #include <boost/serialization/map.hpp>
    #include <boost/thread.hpp>
    #include <boost/thread/mutex.hpp>
    #include <boost/archive/text_oarchive.hpp>
    #include <OgreVector3.h>
     
    /// \class Message
    /// contiend des structures de données utiles pour les messages inter_objets
     
    struct Message{
        std::string nom;
        std::map<std::string, int> i_values;
        std::map<std::string, bool> b_values;
        std::map<std::string, std::string> s_values;
        std::map<std::string, float> f_values;
    //    std::map<std::string, Ogre::Vector3> v_values;
     
        bool operator==(const Message&);
        template<typename Archive>
        void serialize(Archive& ar, const unsigned int){
            ar & BOOST_SERIALIZATION_NVP(i_values);
            ar & BOOST_SERIALIZATION_NVP(b_values);
            ar & BOOST_SERIALIZATION_NVP(s_values);
            ar & BOOST_SERIALIZATION_NVP(f_values);
    //        ar & BOOST_SERIALIZATION_NVP(v_values);
            ar & BOOST_SERIALIZATION_NVP(nom);
     
        }
    };
     
     
    class MessageBox
    {
        public:
            MessageBox();
            virtual ~MessageBox();
     
            virtual void send_message(MessageBox*, Message&);
            virtual void receive_message(Message&);
            virtual void process_queue();
            virtual void process_message(Message&) = 0;
     
            std::string reportMessage(Message& m);
        protected:
            std::queue<Message> _messages;
            boost::mutex _queue_mutex;
    };
     
    #endif // MESSAGEBOX_H
    .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
    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
     
    #include "MessageBox.hpp"
     
    MessageBox::MessageBox()
    {
        //ctor
    }
     
    MessageBox::~MessageBox()
    {
        //dtor
    }
     
    void MessageBox::receive_message(Message& m){
    	_messages.push(m);
    }
     
    void MessageBox::send_message(MessageBox* to, Message& m){
    	to->receive_message(m);
    }
     
    void MessageBox::process_queue(){
    	_queue_mutex.lock();
    	while(!_messages.empty()){
    		Message m;
    		m = _messages.front();
    		_messages.pop();
    		process_message(m);
    	}
    	_queue_mutex.unlock();
    }
     
    std::string MessageBox::reportMessage(Message& m){
        std::ostringstream stream;
        boost::archive::text_oarchive ar(stream);
        ar << m;
        return stream.str();
    }
     
    bool Message::operator==(const Message &m){
        return (nom == m.nom \
                && i_values == m.i_values \
                && b_values == m.b_values \
                && s_values == m.s_values \
                && f_values == m.f_values);
    }
    Et le code de ma classe GraphicsEngine (la classe Engine hérite de IObject, qui hérite de MessageBox)

    .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
     
    #ifndef GRAPHICSENGINE_H
    #define GRAPHICSENGINE_H
     
    #include <iostream>
    #include <Ogre.h>
    #include <CEGUI.h>
    #include <RendererModules\Ogre\CEGUIOgreRenderer.h>
    #include "Engine.hpp"
    #include "../Graphics/WindowListener.hpp"
    #include "../Graphics/GUIListener.hpp"
     
    class GraphicsEngine : public Engine {
        public:
            GraphicsEngine(Game*);
            virtual ~GraphicsEngine();
            void initialise();
            void frame();
            void process_message(Message&);
            void createScene();
            void createViewport();
            void createFrameListener();
        private:
            std::map<std::string, Listener*> _listeners;
     
            CEGUI::OgreRenderer* _renderer;
     
            Ogre::Root* _root;
            Ogre::RenderWindow *_window;
            Ogre::SceneManager *_sceneMgr;
            Ogre::Viewport *_viewport;
     
            Ogre::Camera *_camera;
     
    };
     
    #endif // GRAPHICSENGINE_H
    .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
    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
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
     
    #include "GraphicsEngine.hpp"
    #include "../Game.hpp"
     
    GraphicsEngine::GraphicsEngine(Game* g) : Engine(g), _root(nullptr), _window(nullptr), _sceneMgr(nullptr),
        _viewport(nullptr), _camera(nullptr){
        initialise();
    }
     
    GraphicsEngine::~GraphicsEngine(){
        JLog << std::string("Debut destuction GraphicsEngine");
        delete _root;
        JLog << std::string("Fin destuction GraphicsEngine");
    }
     
    void GraphicsEngine::initialise(){
        _root = new Ogre::Root("plugins.cfg", "ogre.cfg", "Ogre.log");
     
        Ogre::ConfigFile configFile;
        configFile.load("resources.cfg");
     
        Ogre::ConfigFile::SectionIterator seci = configFile.getSectionIterator();
        Ogre::String secName, typeName, archName;
     
        while(seci.hasMoreElements()){
            secName = seci.peekNextKey();
            Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
            Ogre::ConfigFile::SettingsMultiMap::iterator i;
            for(i = settings->begin(); i != settings->end(); ++i){
                typeName = i->first;
                archName = i->second;
                Ogre::ResourceGroupManager::getSingleton().addResourceLocation(archName, typeName, secName);
            }
        }
        if(!(_root->restoreConfig() || _root->showConfigDialog())){
            throw Erreur("Chargement de la config", "Erreur lors du chargement de la configuration du moteur graphique", Tools::CRITICAL);
        }
        _window = _root->initialise(true, "Hello World");
     
        Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);
        Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
     
        _sceneMgr = _root->createSceneManager("DefaultSceneManager", "Mon ScnMgr");
        _sceneMgr->setAmbientLight(Ogre::ColourValue(1.0f, 1.0f, 1.0f));
     
        createScene();
        createViewport();
        createFrameListener();
    }
     
    void GraphicsEngine::createFrameListener(){
        _listeners["Window"] = new WindowListener(_window);
        _listeners["GUI"] = new GUIListener(_window);
     
        for(auto p : _listeners){
            _root->addFrameListener(p.second);
        }
    }
     
    void GraphicsEngine::createScene(){
        _camera = _sceneMgr->createCamera("PlayerCam");
        _camera->setPosition(Ogre::Vector3(0,0,100));
        _camera->lookAt(Ogre::Vector3(0,0,0));
        _camera->setNearClipDistance(5);
     
    //    Ogre::Light *light = _sceneMgr->createLight("Lum");
    //    light->setType(Ogre::Light::LT_POINT);
    //    light->setPosition(0, 0, 100);
    }
     
    void GraphicsEngine::createViewport(){
        _viewport = _window->addViewport(_camera);
        _viewport->setBackgroundColour(Ogre::ColourValue(0, 0, 1.0f));
        _camera->setAspectRatio(Ogre::Real(_viewport->getActualWidth())/Ogre::Real(_viewport->getActualHeight()));
    }
     
    void GraphicsEngine::process_message(Message& mes){
        if(mes.nom == "afficherModele"){
            std::string nom = mes.s_values["nom"];
            Ogre::SceneNode* node = nullptr;
            if(mes.s_values["parent"] == "root"){
                node = _sceneMgr->getRootSceneNode()->createChildSceneNode((nom+"Node"));
            }else{
                node = _sceneMgr->getSceneNode(mes.s_values["parent"])->createChildSceneNode((nom+"Node"));
            }
            Ogre::Entity *ent = _sceneMgr->createEntity((nom + "Ent"), (nom + ".mesh"));
            node->attachObject(ent);
        }else if(mes.nom == "placerPlan"){
        }else{
        }
    }
     
    void GraphicsEngine::frame(){
        Ogre::WindowEventUtilities::messagePump();
        if(!_root->renderOneFrame() || _window->isClosed()/* || !_root->_updateAllRenderTargets()*/){
            Message m;
            m.nom = "stop";
            send_message(_parent, m);
        }
        process_queue();
    }
    Voila... quelqu'un aurait une solution à mon problème ?

    Merci d'avance !
    Dernière modification par koala01 ; 04/07/2013 à 17h52. Motif: utilisation des balises CODE et non QUOTE

  2. #2
    Invité
    Invité(e)
    Par défaut
    Bon ben problème résolu (je suis une buse)

    En fait, j'avais sans doute un conflit avec une quelconque API (sans doute l'API windows)

    J'ai renommé ma classe, et ça compile et linke parfaitement

  3. #3
    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 : 50
    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
    MessageBox est une fonction windows, et comme toutes celles-ci, il s'agit d'un ignoble #define pointant selon les options de compilation vers MessageBoxA ou MessageBoxW. Tant que tout ton code a les mêmes options de compilation (c'est dans l'onglet général, sur les caractères Unicode, MBCS ou aucun), ce #define ne sera pas trop perturbant. Mais si les options diffèrent, le remplacement ne sera que partiel, et tu auras ce genre de soucis.

    Effectivement, renommer la classe peut résoudre le problème, mais peut rendre le code moins clair. Une autre solution est d'harmoniser tes options de compilation (ce qui est souhaitable de toute manière).

  4. #4
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Décembre 2010
    Messages
    734
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Décembre 2010
    Messages : 734
    Points : 1 475
    Points
    1 475
    Par défaut
    Sinon, ne serais-ce pas une excellente illustration de l'utilité des namespaces?

  5. #5
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 381
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 381
    Points : 41 582
    Points
    41 582
    Par défaut
    Il n'y a pas seulement les options de compilation, mais aussi le fait d'inclure ou non <windows.h> avant les headers qui définissent la classe.

    Une autre option serait de les #undef dans le header de la classe, puis les re-#define à la fin de ce header (plus un #undef dans le .cpp qui implémenta la classe).

    Code C++ : 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
    //Garde d'inclusion
    //(remplacer par #pragma once si tous les environnements cibles le supportent)
    #ifndef H_MESSAGEBOX_20130705
    #define H_MESSAGEBOX_20130705
     
    #ifdef MessageBox
    #define NEED_REDEF_MessageBox_20130705
    #undef MessageBox
    #endif
     
    class MessageBox
    {
    ...
    };
     
    #ifdef NEED_REDEF_MessageBox_20130705
    #ifdef UNICODE
    #define MessageBox MessageBoxW
    #else
    #define MessageBox MessageBoxA
    #endif
    #undef NEED_REDEF_MessageBox_20130705
    #endif
     
    #endif // ! H_MESSAGEBOX_20130705

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

Discussions similaires

  1. [Runtime class loading] Appeler une méthode qui n'existe pas
    Par Invité dans le forum Général Java
    Réponses: 14
    Dernier message: 27/06/2008, 08h48
  2. Charger dynamiquement une classe qui n'est pas dans un jar
    Par rastakouair dans le forum Langage
    Réponses: 12
    Dernier message: 17/12/2007, 19h22
  3. Afficher une liste qui n'existe pas dans la base de données.
    Par Zvetch dans le forum SAP Crystal Reports
    Réponses: 1
    Dernier message: 25/09/2007, 13h23
  4. Pb avec hibernate3, il cherche une table qui n'existe pas
    Par yeddoughmi dans le forum Hibernate
    Réponses: 2
    Dernier message: 22/08/2007, 12h08
  5. Réponses: 8
    Dernier message: 26/01/2006, 14h47

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