Partage
  • Partager sur Facebook
  • Partager sur Twitter

Mes attributs perdent la mémoire.

Sujet résolu
Anonyme
    2 août 2007 à 14:16:00

    Bonjour!
    Je sais qu'il y a pas mal de code, mais aidez moi SVP :) Merci d'avance

    Je suis entrain de m'entrainer aux classe an créant des menu en SDL.
    Mais j'en suis déjà à mon troisième problème :-° .

    Cette fois le problème est que mes attribut ne gardent pas en mémoire longtemps la valeur voulue.

    J'explique un peu comment fonctionne mon code avant de donner plus de détails.

    Pour créer un menu, j'ai créé une class MenuSDL. Si on veut ajouter un élément au menu, il faut appeler la méthode add_actionMenuSDL, ce qui rajoute un élément de la class ActionMenuSDL dans un vector (c_VActMenu).

    Jusqu'à la c'est bon le programme marche.

    Je me suis dis que ce serait bien de pouvoir supprimer un élément du menu, alors j'ai rajouté un attribut c_id à la class ActionMenuSDL. La valeur de cet attribut est gérée par la class MenuSDL.
    Lors de la création du nouveau élément ActionMenuSDL, l'id de ce dernier est retourné par add_actionMenuSDL, comme ça on peux la stoker facilement.

    Mais le problème c'est que l'attribut c_id ne garde pas sa valeur très longtemps, elle change en sortant du constructeur pour se mettre à 0.

    J'ai relus, revu, fait de test en long et en large mais je ne trouve pas d'où vient le problème. :(

    Voici la partie de mon code qui devrait vous être utile pour m'aider :

    class ActionMenuSDL
    {
        public:
            ActionMenuSDL(int x, int y, int w, int h,
                   SDL_Surface *surf, void (*fctToCall)(void), unsigned int id = 0);
            ~ActionMenuSDL(void);
            void freeSurf(void);

            ActionMenuSDL(const ActionMenuSDL &actionMenu);

            unsigned int main(int mouseX, int mouseY);
            // Retourne l'id du ActionMenuSDL executé (0 si aucun n'est executé).

            SDL_Surface* get_surf(void);
            SDL_Rect* get_pRect(void);

        private:
            SDL_Rect c_rect;
            SDL_Surface *c_surf;
            void (*c_fctToCall)(void);

            unsigned int c_id;

    };

    ActionMenuSDL::ActionMenuSDL(int x, int y, int w, int h, SDL_Surface *surf,
       void (*fctToCall)(void), unsigned int id) :  c_fctToCall(fctToCall), c_id(id)
    {
        c_rect.x = x;
        c_rect.y = y;
        c_rect.w = w;
        c_rect.h = h;

        c_surf = SDL_DisplayFormat(surf);
    }

    unsigned int ActionMenuSDL::main(int mouseX, int mouseY)
    {
        if (mouseX > c_rect.x && mouseX < (c_rect.x + c_rect.w) &&
                                mouseY > c_rect.y && mouseY < (c_rect.y + c_rect.h))
        {
            (*c_fctToCall)();
            return c_id;
        }
        return 0;
    }

    class MenuSDL
    {
        public:
            MenuSDL(int w, int h, int x = 0, int y = 0);
            ~MenuSDL(void);
            void freeSurf(void);

            void set_backgroundColor(Uint32 *couleur);
            void set_backgroundColor(int r, int g, int b);
            void set_backgroundImage(SDL_Surface* img, int x = 0, int y = 0);
            void set_pos(int x = 0, int y = 0);
            void set_size(int w, int h);

            unsigned int add_actionMenuSDL(int x, int y, int w, int h,
                                        SDL_Surface *surf, void (*fctToCall)(void));
            // Retourne l'id du ActionMenuSDL créé.

            void blit(SDL_Rect *zone = 0,
                                         SDL_Surface *dest = SDL_GetVideoSurface());

            unsigned int main(int mouseX, int mouseY);
            // Retourne l'id du ActionMenuSDL executé (0 si aucun n'est executé).

        private:
            SDL_Surface *c_menu, *c_backgroundImg;
            SDL_Rect c_rect, c_posImg;
            Uint32 c_couleur;

            typedef std::vector<ActionMenuSDL> VecteurActionMenuSDL;
            VecteurActionMenuSDL c_VActMenu;
            unsigned int c_nbIdActMenu;

            void blitActMenus(void);
            void blitAll(void);

    };

    unsigned int MenuSDL::add_actionMenuSDL(int x, int y, int w, int h,
                                         SDL_Surface *surf, void (*fctToCall)(void))
    {
        c_nbIdActMenu++;
        c_VActMenu.push_back(ActionMenuSDL(x, y, w, h, surf,
                                                         fctToCall, c_nbIdActMenu));

        blitAll();

        return c_nbIdActMenu;
    }

    unsigned int MenuSDL::main(int mouseX, int mouseY)
    {
        unsigned int id = 0;
        for (unsigned int i = 0; i < c_VActMenu.size() && id == 0; i++)
            id = c_VActMenu[i].main(mouseX, mouseY);

        return id;
    }

    // et une partie du main :
    MenuSDL menu(200, 500);
    unsigned int id_1 = menu.add_actionMenuSDL(50, 175, 150, 220, cb, &fct); // id_i = 1
    unsigned int id_2 = menu.add_actionMenuSDL(50, 0, 150, 220, cb, &fct2); // id_2 = 2

    SDL_Event event;
    SDL_WaitEvent(&event);
    switch (event.type)
    {
        unsigned int id;
        case SDL_MOUSEBUTTONDOWN:
            id = menu.main(event.button.x, event.button.y);
            cout << id << endl; // id = toujours 0! pas normal.
            break;
    }
     


    Merci beaucoup de m'aider. :)
    Hiura
    • Partager sur Facebook
    • Partager sur Twitter
      2 août 2007 à 15:20:42

      Si je me souviens bien, l'origine de l'écran est en haut à gauche, ce qui fait qu'on se retrouve dans le 4e quadrant du plan cartésien ( x+, y- ). Donc pour calculer la position des y ce ne serait pas si
      MouseY < c_rect.y && MouseY > (c_rect.y - c_rect.h)
      • Partager sur Facebook
      • Partager sur Twitter
        2 août 2007 à 15:31:34

        Pour commencer, pourquoi tu n'utilises pas le type FUNC dont je t'avais parlé??

        typedef void (*FUNC)(void);


        D'ailleurs que tu appelles la fonction, pas la peine d'écrire : (*fctToCall)(), et tu n'as pas besoin non plus de mettre &fct quand tu passes la fonction... Le nom d'une fonction sans les parenthèses représentent déjà son pointeur.

        À part ça, ce que je te conseille d'essayer, c'est de mettre un petit

        cout << "Nouvel item : " << c_id << endl;


        dans le constructeur de tes objets de menu, ça te permettra de tracer le nombre d'éléments.
        • Partager sur Facebook
        • Partager sur Twitter
        Anonyme
          2 août 2007 à 15:55:37

          Citation : MatteX

          Si je me souviens bien, l'origine de l'écran est en haut à gauche, ce qui fait qu'on se retrouve dans le 4e quadrant du plan cartésien ( x+, y- ). Donc pour calculer la position des y ce ne serait pas si

          MouseY < c_rect.y && MouseY > (c_rect.y - c_rect.h)

          Non car quand tu descant sur l'axe des y, sa valeur augemente (c'est pas très commun comme système mais bon).


          Citation : psychoh13

          Pour commencer, pourquoi tu n'utilises pas le type FUNC dont je t'avais parlé??

          typedef void (*FUNC)(void);




          Non je ne l'ai pas encore fait, mais ne va pas croire que je ne t'ai pas écouté ;) , je l'implémenterais plus tard dans mon projet.

          Citation : psychoh13

          À part ça, ce que je te conseille d'essayer, c'est de mettre un petit


          cout << "Nouvel item : " << c_id << endl;




          dans le constructeur de tes objets de menu, ça te permettra de tracer le nombre d'éléments.



          Oui c'est d'ailleurs comme ça que j'ai vue que qqch n'allait pas, je l'ai simplement enlevé pour pas trop surcharger le code ci-dessus.

          J'avais mis :

              cout << c_id << "°>" << id << endl;

          dans le constructeur de ActionMenuSDL. Les deux valeurs sont les mêmes, mais j'avais aussi mis :
          cout << "*" << c_id << endl;

          dans une fonction* qui se fait appelé par blitAll (qui est appelée entre autre dans add_actionMenuSDL).

          *c'est une des méthodes de la class ActionMenuSDL.


          Citation : psychoh13

          D'ailleurs que tu appelles la fonction, pas la peine d'écrire : (*fctToCall)(), et tu n'as pas besoin non plus de mettre &fct quand tu passes la fonction... Le nom d'une fonction sans les parenthèses représentent déjà son pointeur.



          Mais question propreté/efficacité/rapidité, est-ce la même chose?

          Hiura
          • Partager sur Facebook
          • Partager sur Twitter
            2 août 2007 à 16:19:18

            Citation : psychoh13

            Pour commencer, pourquoi tu n'utilises pas le type FUNC dont je t'avais parlé??

            typedef void (*FUNC)(void);


            Oui c'est vrai tu peux ainsi facilement créer un type de fonction pointée à l'intérieur de ta classe (public) et déclarer tout tes pointeurs de fonction comme cela
            FUNC pf; // je viens de déclarer une fonction void(*pf)()
             


            J'ajoute ce commentaire parce que dans ton autre post je crois que tu avais bien dit que tu ne comprennais pas le but de cette technique

            Citation : psychoh13

            D'ailleurs que tu appelles la fonction, pas la peine d'écrire : (*fctToCall)()[...]


            Si! C'est nécessaire de déréférencer le pointeur vers son espace pointé entre les parenthèses pour pouvoir l'appeler... je vais essayer de l'imager avec un pointeur d'objet de type string:
            string * p_str = new string( "Salut!" );
            size_t taille = (*p_str).size();
            //lecture d'un caractère
            (*p_str)[ taille - 1 ];
            delete p_str; // tant qu'à faire un bon exemple
             


            Pourquoi? parce que les opérateurs unaires s'appliquent avant l'opérateur de déférencement
            Ref : http://casteyde.christian.free.fr/cpp/cours/online/a9632.html


            Citation : psychoh13

            [...] et tu n'as pas besoin non plus de mettre &fct quand tu passes la fonction... Le nom d'une fonction sans les parenthèses représentent déjà son pointeur.



            encore faux! Tu dois effectivement retrouver l'adresse de la fonction grâce à l'opérateur unaire "&". La fonction n'est pas un tableau, elle existe en mémoire comme une variable.

            [EDIT]Et bien je me suis planté solide! La preuve qu'on apprend tout les jours. Toute DOC n'est pas toujours bonne à lire :p[/EDIT]
            • Partager sur Facebook
            • Partager sur Twitter
            Anonyme
              2 août 2007 à 17:04:45

              Merci bien pour ces infos, mais ça ne résouts pas mon problème :lol: (rire désespéré après avoir chercher pendant des heures).
              • Partager sur Facebook
              • Partager sur Twitter
                2 août 2007 à 17:44:08

                Visiblement t'as rien compris de ce que j'ai dit MatteX !

                Citation : MatteX

                Citation : psychoh13

                D'ailleurs que tu appelles la fonction, pas la peine d'écrire : (*fctToCall)()[...]


                Si! C'est nécessaire de déréférencer le pointeur vers son espace pointé entre les parenthèses pour pouvoir l'appeler... je vais essayer de l'imager avec un pointeur d'objet de type string:



                Non seulement ton "exemple" n'a ABSOLUMENT aucun rapport avec les pointeurs de fonctions, mais en plus ce que je disais c'est que, pour appeler une fonction tu n'avais pas besoin d'écrire :

                (*fctToCall)();


                Mais tu peux écrire directement ça :

                fctToCall();


                Citation : MatteX

                encore faux! Tu dois effectivement retrouver l'adresse de la fonction grâce à l'opérateur unaire "&". La fonction n'est pas un tableau, elle existe en mémoire comme une variable.



                Désolé, mais ce n'est pas nécessaire ! Le nom d'une fonction représente aussi son pointeur !

                Essaye ce code pour t'en convaincre :

                #include <iostream>

                int caller(int (*called)(int), int value)
                {
                    return called(value);
                }

                int callee(int valeur)
                {
                    return valeur * 5;
                }

                int main(int argc,char* argv[])
                {
                    std::cout << "Valeur : " << caller(callee, 10) << std::endl;
                   
                    return 0;
                }
                • Partager sur Facebook
                • Partager sur Twitter
                  2 août 2007 à 17:57:19

                  d'ah! J'étais pourtant sur que le nom ne fesait pas référence à la fonction

                  Tu l'as bien gagnée celle là ;)
                  • Partager sur Facebook
                  • Partager sur Twitter
                    2 août 2007 à 18:09:59

                    Héhé ;)

                    Bon hiura... Ce pense que tu devrais tenter d'afficher beaucoup plus d'informations, par exemple dans tes main(), affiche les tailles de tes objets (x, y, w et h) et affiche aussi la position de la souris, affiche aussi dans les boucles tous les ids...

                    En clair, affiche les valeurs significatives de tes fonctions à tous les niveaux.
                    • Partager sur Facebook
                    • Partager sur Twitter
                    Anonyme
                      2 août 2007 à 19:15:54

                      Je vais aller me terrer dans un trou je crois. :-°

                      J'ai honte de moi. :(

                      faire une bêtise pareille!! :colere2:

                      Merci psychoh13 pour ton idée des cout et co. Je l'avais déjà fait mais pas à ce point là, et c'est ça qui m'a tout indiqué.

                      Enfait je m'étais focalisé sur le constructeur et pas sur le "copieur". j'avais oublié juste une ligne :

                          c_id = actionMenu.c_id;


                      Que je suis bête!

                      En tout cas merci à tous!
                      Hiura
                      • Partager sur Facebook
                      • Partager sur Twitter

                      Mes attributs perdent la mémoire.

                      × 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