Partage
  • Partager sur Facebook
  • Partager sur Twitter

POO

problème avec membres statiques

    18 juin 2007 à 14:42:37

    Bonjour,
    je suis en train d'essayer d'utiliser la POO avec SDL, notament pour
    charger des surfaces. J'ai réalisé le code suivant:

    WindowHandler.h:
    #ifndef WH_H
    #define WH_H

    #include <SDL/SDL.h>

    class WindowHandler
    {
    public:
        WindowHandler();
        ~WindowHandler();
        static bool isReady();
    private:
        static bool m_SDL_initialized;
        static SDL_Surface *m_screen;
    };

    #endif


    WindowHandler.cpp:
    #ifndef WH_CPP
    #define WH_CPP

    #include <SDL/SDL.h>
    #include "WindowHandler.h"

    WindowHandler::WindowHandler()
    {
        if(WindowHandler::m_SDL_initialized)
        {
            SDL_Init(SDL_INIT_VIDEO);
            WindowHandler::m_screen = SDL_SetVideoMode(640, 480, 16, SDL_HWSURFACE|SDL_DOUBLEBUF);
            WindowHandler::m_SDL_initialized = true;
        }
    }

    WindowHandler::~WindowHandler()
    {
        SDL_Quit();
    }

    bool WindowHandler::isReady()
    {
        return WindowHandler::m_SDL_initialized;
    }

    #endif


    main.cpp:
    #include <cstdlib>
    #include <SDL/SDL.h>
    #include "WindowHandler.h"

    int main ( int argc, char** argv )
    {
        SDL_Init(SDL_INIT_VIDEO);

        WindowHandler window;

        bool continue_ = true;
        SDL_Event event;

        while (continue_)
        {
            SDL_WaitEvent(&event);
            switch(event.type)
            {
                case SDL_QUIT:
                    continue_ = false;
            }
        }

        return 0;
    }


    Le code compile sans aucune erreur mais j'ai ce message:
    .objs\WindowHandler.o:WindowHandler.cpp:(.text+0x8): undefined reference to `WindowHandler::m_SDL_initialized'
    .objs\WindowHandler.o:WindowHandler.cpp:(.text+0x34): undefined reference to `WindowHandler::m_screen'
    .objs\WindowHandler.o:WindowHandler.cpp:(.text+0x3a): undefined reference to `WindowHandler::m_SDL_initialized'
    .objs\WindowHandler.o:WindowHandler.cpp:(.text+0x4a): undefined reference to `WindowHandler::m_SDL_initialized'
    .objs\WindowHandler.o:WindowHandler.cpp:(.text+0x76): undefined reference to `WindowHandler::m_screen'
    .objs\WindowHandler.o:WindowHandler.cpp:(.text+0x7c): undefined reference to `WindowHandler::m_SDL_initialized'
    .objs\WindowHandler.o:WindowHandler.cpp:(.text+0xa6): undefined reference to `WindowHandler::m_SDL_initialized'

    collect2: ld returned 1 exit status

    Il est claire que ce sont les attributs (tous statiques) de la
    classe WindowHandler qui posent problème.

    Merci d'avance et dites moi si l'anglais vous gêne.
    • Partager sur Facebook
    • Partager sur Twitter
      18 juin 2007 à 16:43:32

      • Tu initialises la SDL 2 fois...
      • N'inclus pas 36 fois un header : SDL/SDL.h est déjà inclus dans WindowHandler.h, donc ne le refais pas dans main (ni dans WindowHandler.h)
      • Au niveau des "préfixes de résolution de portée" : tu peux éviter d'utiliser WindowHandler:: ...
      • Les membres statiques doivent être définis dans le fichier source implémentant la classe les encapsulant.
      Mais surtout : Les membres statiques ne peuvent être manipulés que par des méthodes statiques ! (donc pas dans le contructeur)

      P.S:

      Citation : Toi

      et dites moi si l'anglais vous gêne.


      Si c'était le cas, je ne pense pas que nous devrions continuer à développer...

      Comme je le dis toujours, un programmeur anglophobe est déjà à la retraite.
      • Partager sur Facebook
      • Partager sur Twitter
        18 juin 2007 à 17:00:25

        tu doit definir la valeur des objet static avant des les utiliser :

        bool WindowHandler::m_SDL_initialized = 0; // etc...


        dans le cpp associé a ton objet.

        si je suis pas tres clair (pas du tout impossible) : http://frog.isima.fr/antoine/base.shtml

        vers la fin de la page il y a de bonne explication sur les variables static.

        EDIT:@ kidpaddle2

        Citation : kidpaddle2

        Les membres statiques ne peuvent être manipulés que par des méthodes statiques ! (donc pas dans le contructeur)



        je suis vraiment pas sur (meme si l'inverse est vrai; une méthode static ne peut accéder qu'aux attributs static de la classe.)

        exemple pris sur http://www.cprogramming.com/tutorial/statickeyword.html

        class user
        {
          private:
          int id;
          static int next_id;

          public:
          static int next_user_id()
          {
            next_id++;
            return next_id;
          }
          /* More stuff for the class user */
          user()
          {
            id = user::next_id++; //or, id = user.next_user_id();
          }
        };
        int user::next_id = 0;

        la fonction user (le constructeur en l'occurence !) lit ET écrit dans des variables static...
        • Partager sur Facebook
        • Partager sur Twitter
        Anonyme
          18 juin 2007 à 17:14:26

          "Mais surtout : Les membres statiques ne peuvent être manipulés que par des méthodes statiques ! (donc pas dans le contructeur)"

          Non, les méthodes non static peuvent utiliser les attributs et méthodes static, mais les méthodes static ne peuvent utiliser les fonctions membres et attributs non static.

          Un attribut static de classe n'est qu'une variable globale dont le nom est décoré du nom de la classe, donc ne jamais oublié que si on a :

          A.h :

          #ifndef _A
          #define _A
          class A{
              // déclaration
              static int a;
          };
          #endif


          On doit avoir un A.cpp contenant :


          // définition
          int A::a; // et éventuellement initialisation : int A::a=0;
          • Partager sur Facebook
          • Partager sur Twitter
            18 juin 2007 à 17:34:32

            Pardonnez moi je ne sais plus ce que je dis, c'est inéluctablement vrai (sinon je ne vois pas l'intérêt).

            C'est simplement la définition (et non la déclaration) qui pose problème.

            Edit: D'ailleurs, ce serait alors des erreurs de compilation, et non de linker.
            • Partager sur Facebook
            • Partager sur Twitter
              18 juin 2007 à 20:15:49

              Citation : kidpaddle2

              <puce>N'inclus pas 36 fois un header : SDL/SDL.h est déjà inclus dans WindowHandler.h, donc ne le refais pas dans main (ni dans WindowHandler.h)</puce>



              Tu inclus tout ce dont tu as de besoin là où tu en as de besoin. Même si c'est la 36e fois.
              • Partager sur Facebook
              • Partager sur Twitter
                18 juin 2007 à 20:24:46

                Du moment que l'inclusion n'est pas à "perpette" dans la hiérarchie de fichiers*, je ne vois pas pourquoi nous devrions nous prendre la tête avec des lignes de codes ne servant fichtrement à rien.

                De plus, pour peu que les headers soient conséquents, cela ne ferait que grossir la taille de l'exécutable final : certains s'acharnent -toujours pour ce problème de taille- sur des "petits" (souvent) détails comme la mise inline des fonctions, alors imagine quant aux headers...

                * : Comprendre pour des proximités immédiates, comme deux headers ou un couple header/fichier source...
                • Partager sur Facebook
                • Partager sur Twitter
                Anonyme
                  18 juin 2007 à 20:27:10

                  Euh...il me semble que même si tu inclues 50 fois un header, dans l'exécutable final il ne sera présent qu'une seule fois, grâce aux guards. Donc au final, ça ne coûte rien et c'est mieux ;) .
                  • Partager sur Facebook
                  • Partager sur Twitter
                    18 juin 2007 à 20:32:53

                    Je vous remercie de vos réponses. J'ai pu faire un code qui compile,
                    mais qui me pose problème: à la place d'avoir une fenêtre toute noir
                    (ce que j'attendait en gros) j'ai une console vide que je ferme et un
                    CPU utilisé à 100% par ma fenêtre invisible. Ca m'oblige à redémarrer.

                    voici mon nouveau code défaillant

                    WindowHandler.h:
                    #ifndef WH_H
                    #define WH_H

                    #include <SDL/SDL.h>

                    class WindowHandler
                    {
                    public:
                        WindowHandler();
                        ~WindowHandler();
                        static bool isReady();
                    private:
                        static bool m_SDL_initialized;
                        static SDL_Surface *m_screen;
                    };

                    #endif


                    WindowHandler.cpp:
                    #ifndef WH_CPP
                    #define WH_CPP

                    #include <SDL/SDL.h>
                    #include "WindowHandler.h"

                    bool WindowHandler::m_SDL_initialized = false;
                    SDL_Surface *WindowHandler::m_screen = 0;

                    WindowHandler::WindowHandler()
                    {
                        if(m_SDL_initialized)
                        {
                            SDL_Init(SDL_INIT_VIDEO);
                            WindowHandler::m_screen = SDL_SetVideoMode(640, 480, 16, SDL_HWSURFACE|SDL_DOUBLEBUF);
                            WindowHandler::m_SDL_initialized = true;
                        }
                    }

                    WindowHandler::~WindowHandler()
                    {
                        SDL_Quit();
                    }

                    bool WindowHandler::isReady()
                    {
                        return m_SDL_initialized;
                    }

                    #endif


                    main.cpp
                    #include <cstdlib>
                    #include <SDL/SDL.h>
                    #include "WindowHandler.h"

                    int main ( int argc, char** argv )
                    {
                        WindowHandler window;

                        bool continue_ = true;
                        SDL_Event event;

                        while (continue_)
                        {
                            SDL_WaitEvent(&event);
                            switch(event.type)
                            {
                                case SDL_QUIT:
                                    continue_ = false;
                            }
                        }

                        return 0;
                    }


                    C'est peut-être pas grand chose. Merci encore!
                    • Partager sur Facebook
                    • Partager sur Twitter
                      18 juin 2007 à 20:35:04

                      Tu as raison Cyprien_ les headers ne servent qu'à déclarer les entités ( fonctions, classes, etc ) qui pourraient être utilisées dans les fichiers. Cela ne coûte rien de plus. Ont les inclus partout où nécessaire pour évité les mots de têtes de gestion des fichiers inclus en cascade... et il y a divers système pour évité les inclusions multiples
                      • Partager sur Facebook
                      • Partager sur Twitter
                        20 juin 2007 à 9:13:44

                        par hasard ... sa serai pas
                        if(!m_SDL_initialized)
                        non ?

                        et ensuite pour eviter des erreurs de ce type tu a deja une mini gestion d'erreur dans ton programme :
                        bool continue_ = window.isReady();

                        comme sa tu entre dans la boucle que si ta fenêtre a été chargé ^^
                        • Partager sur Facebook
                        • Partager sur Twitter
                          20 juin 2007 à 15:31:38

                          if(m_SDL_initialized)
                          {
                                  SDL_Init(SDL_INIT_VIDEO);
                                  WindowHandler::m_screen = SDL_SetVideoMode(640, 480, 16, SDL_HWSURFACE|SDL_DOUBLEBUF);
                                  WindowHandler::m_SDL_initialized = true;
                          }


                          m_SDL_initialized = true;? tu devrais verifier que ton setVideo a fonctionner avant de mettre cette variable à true.. (m_screen != NULL)??

                          bonne continuation
                          • Partager sur Facebook
                          • Partager sur Twitter

                          POO

                          × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                          × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                          • Editeur
                          • Markdown