Partage
  • Partager sur Facebook
  • Partager sur Twitter

Objets en C++

    22 juin 2017 à 21:06:53

    Bonsoir,

    J'ai une petite question à propos du code suivant

    class A {
    
    private:
      B b;
    
    public:
    
    
    };
    class B {
    
    private:
      int test=0;
    
    public:
    void update(){test++;};
    
    };

    La modification n'est pas pris en compte lors du prochaine appel à update(); Je me demande donc si j'ai besoin d'utiliser un pointeur vers b dans la classe A.

    Merci pour votre aide :)

    • Partager sur Facebook
    • Partager sur Twitter
      23 juin 2017 à 0:26:09

      La modification de quoi?

      Pour tout objet de type B, appeler sa fonction update() incrémentera son membre test.
      Si on s’intéresse au b qui à l'intérieur des objets de type A, cela est donc aussi vrai pour lui.
      Tel que c'est écrit ici, le 'b' n'est accessible de personne, à part d'éventuelles fonctions de A qui pourraient faire b.update(). Sans une fonction, b ne sera jamais modifié. 
      'b' est un membre inclus dans A, on ne peut pas faire mieux, je ne vois pas où utiliser un pointeur aurait un quelconque rôle.

      • Partager sur Facebook
      • Partager sur Twitter

      En recherche d'emploi.

        23 juin 2017 à 10:11:54

        La modification de la variable test.

        Je ne sais pas pourquoi lorsque la fontion update est appelé plusieurs fois , la variable test est toujours a 0.

        • Partager sur Facebook
        • Partager sur Twitter
          23 juin 2017 à 10:20:45

          Tu peux nous montrer ton code ou tu appelles le update() ?

          ça devrait fonctionner. à moins que tu fasses un new à chaque fois...

          • Partager sur Facebook
          • Partager sur Twitter
            23 juin 2017 à 10:20:59

            Ben on ne peut pas savoir non plus puisqu'on n'a pas le code appelant. Mais ça sent les copies fortuites.

            Punt a écrit:

            ça devrait fonctionner. à moins que tu fasses un new à chaque fois...

            Vu qu'il faut jamais utiliser new en C++, tout va bien.

            -
            Edité par Ksass`Peuk 23 juin 2017 à 10:21:35

            • Partager sur Facebook
            • Partager sur Twitter

            Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C

              23 juin 2017 à 10:46:38

              En faite si j'ai fait un new pour la classe A.

              J'ai une classe game contenant un tableau de  pointeur de projectiles

              chaque projectile possède une classe Animation qui correspond ici à la classe B.

              et mon update est appelé comme ça

              (*itorProjectiles)->getAnimation().update(SDL_GetTicks() - timerAnimProjectiles);



              -
              Edité par joezzz 23 juin 2017 à 10:50:02

              • Partager sur Facebook
              • Partager sur Twitter
                23 juin 2017 à 11:02:00

                Il faut donner plus de code. Idéalement, un code minimal reproduisant l'erreur.

                Le problème est que tu sembles mal cerner l'origine du problème et donc que tu ne donnes pas le code qui pose probleme. (On ne sait pas par exemple ce que fait exactement "getAnimation").

                Il ne faut pas donner trop de code, pour ne pas faire perdre leur temps a ceux qui t'aide. Mais si tu n'en donnes pas assez, tu as le meme effet.

                • Partager sur Facebook
                • Partager sur Twitter
                  23 juin 2017 à 11:02:39

                  joezzz a écrit:

                  En faite si j'ai fait un new pour la classe A.

                  Donc commence par ne pas faire ça, parce que tu n'as très probablement pas le niveau en C++ pour jouer à ça (et quand tu auras le niveau, tu le fuiras comme la peste parce que tu sauras que tu toujours te débrouiller sans et que ça t'évitera de faire des conneries).

                  joezzz a écrit:

                  (*itorProjectiles)->getAnimation().update(SDL_GetTicks() - timerAnimProjectiles);

                  Au hasard, je dirai que la fonction "getAnimation()" renvoie par copie.

                  • Partager sur Facebook
                  • Partager sur Twitter

                  Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C

                    23 juin 2017 à 11:07:54

                    La fonction getAnimation c'est juste ça

                    Animation getAnimation(){return mAnimation;};

                    et j'utilise un new car je procède comme cela pour la création des projectiles

                    void Soldier::attack(std::list<Projectile *> *projectiles)
                    {
                        if(SDL_GetTicks() - time>= 1000 - attackSpeed*1000)
                        {
                            shooting = true;
                            time = SDL_GetTicks();
                            Projectile *p = new Projectile(Animation("rocket", 500, 2, true), shootingProjectilePointX, shootingProjectilePointY, 31, 19, cos(angleAttack * 3.14159265/ 180), sin(angleAttack * 3.14159265/ 180));
                            p->setAngle(angleAttack);
                            projectiles->push_back(p);
                    
                            if(SDL_GetTicks() - timeShootingAnimation>= 200)
                            {
                                timeShootingAnimation = SDL_GetTicks();
                                shooting = false;
                            }
                        }
                    }




                    • Partager sur Facebook
                    • Partager sur Twitter
                      23 juin 2017 à 11:11:05

                      joezzz a écrit:

                      La fonction getAnimation c'est juste ça

                      Animation getAnimation(){return mAnimation;};

                      Tada ! Elle renvoie une copie, comme je le soupçonnais. Donc tu modifies une copie de l'objet et pas l'objet lui même.

                      joezzz a écrit:

                      et j'utilise un new car je procède comme cela pour la création des projectiles

                      void Soldier::attack(std::list<Projectile *> *projectiles)
                      {
                          if(SDL_GetTicks() - time>= 1000 - attackSpeed*1000)
                          {
                              shooting = true;
                              time = SDL_GetTicks();
                              Projectile *p = new Projectile(Animation("rocket", 500, 2, true), shootingProjectilePointX, shootingProjectilePointY, 31, 19, cos(angleAttack * 3.14159265/ 180), sin(angleAttack * 3.14159265/ 180));
                              p->setAngle(angleAttack);
                              projectiles->push_back(p);
                      
                              if(SDL_GetTicks() - timeShootingAnimation>= 200)
                              {
                                  timeShootingAnimation = SDL_GetTicks();
                                  shooting = false;
                              }
                          }
                      }

                      Alors :

                      • rien ne justifie que tu passes ta liste par un pointeur, ça devrait être un passage par référence,
                      • rien ne justifie que tu utilises un pointeur nu + new pour ton projectile plutôt que std::unique_ptr,
                      • conséquence fortuite : ton code contient un chemin de fuite à cause de la mécanique d'exception, d'où le fait qu'utiliser "new", c'est pas pour les débutants.
                      • Partager sur Facebook
                      • Partager sur Twitter

                      Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C

                        23 juin 2017 à 11:11:08

                        Et donc, si l'appel à l'operateur new echoue (pour une raison quelconque), tu obtiens ...................... *roulements de tambours*............................... une fuite de memoire.
                        • Partager sur Facebook
                        • Partager sur Twitter
                          23 juin 2017 à 11:13:32

                          Deedolith a écrit:

                          Et donc, si l'appel à l'operateur new echoue (pour une raison quelconque), tu obtiens ...................... *roulements de tambours*............................... une fuite de memoire.

                          (C'est plutôt l'appel à push_back qui va nous mettre dedans ici, l'échec de new dans cette fonction ne provoque pas de catastrophe).

                          EDIT : enfin, sauf si la pile de fonctions appelantes a fait une allocation dynamique explicite avant d'atteindre ce new quand même.

                          -
                          Edité par Ksass`Peuk 23 juin 2017 à 11:14:37

                          • Partager sur Facebook
                          • Partager sur Twitter

                          Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C

                            23 juin 2017 à 11:21:39

                            Ksass`Peuk a écrit:

                            EDIT : enfin, sauf si la pile de fonctions appelantes a fait une allocation dynamique explicite avant d'atteindre ce new quand même.

                            -
                            Edité par Ksass`Peuk il y a 4 minutes


                            Ce que je suspecte grandement, l'OP instancie dynamiquement des projectiles, en toute logique, il a instancié dynamiquement au moins 1 soldat au préalable.
                            • Partager sur Facebook
                            • Partager sur Twitter
                              23 juin 2017 à 12:14:23

                              Deedolith a écrit:

                              Ksass`Peuk a écrit:

                              EDIT : enfin, sauf si la pile de fonctions appelantes a fait une allocation dynamique explicite avant d'atteindre ce new quand même.

                              -
                              Edité par Ksass`Peuk il y a 4 minutes


                              Ce que je suspecte grandement, l'OP instancie dynamiquement des projectiles, en toute logique, il a instancié dynamiquement au moins 1 soldat au préalable.

                              Non pour les soldats j'ai simplement fait ça

                              Soldier s;
                              entities.push_back(s);

                              Je vais modifier selon ce que vous avez dit, je repost dans l'après midi après avoir fait les corrections. 


                              • Partager sur Facebook
                              • Partager sur Twitter
                                23 juin 2017 à 12:39:23

                                Cela implique une copie de l'objet Soldier (bof) et que Soldier est copiable (bof bof).
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  23 juin 2017 à 16:41:17

                                  En suivant vos conseils j'obtiens le code suivant

                                  void Soldier::attack(std::list<std::unique_ptr<Projectile>> & projectiles)
                                  {
                                      if(SDL_GetTicks() - time>= 1000 - attackSpeed*1000)
                                      {
                                          shooting = true;
                                          time = SDL_GetTicks();
                                          std::unique_ptr<Projectile> projectile(new Projectile(Animation("rocket", 500, 2, true), shootingProjectilePointX, shootingProjectilePointY, 31, 19, cos(angleAttack * 3.14159265/ 180), sin(angleAttack * 3.14159265/ 180)));
                                          projectile->setAngle(angleAttack);
                                          projectiles.push_back(projectile);
                                  
                                          if(SDL_GetTicks() - timeShootingAnimation>= 200)
                                          {
                                              timeShootingAnimation = SDL_GetTicks();
                                              shooting = false;
                                          }
                                      }
                                  }

                                  Le problème est que j'obtiens une erreur lors de la creation du pointeur unique qui me dit "use of deleted function".

                                  De plus je me demande si c'est en écrivant directement

                                  Animation("rocket", 500, 2, true)


                                   que je dois init la classe Animation qui est un attribut de la classe projectile.

                                  Sinon pour la question du getAnimation il faut donc que je retourne un pointeur de l'objet pour pouvoir le modifier ?

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    23 juin 2017 à 16:44:50

                                    Quand tu donnes une erreur, il faut la donner complètement. Normalement, l'erreur indique la ligne de code corresponde et le code qui pose problème.

                                    J'imagine ici que le problème est dans le push_back, pas dans le constructeur ?

                                    projectiles.push_back(std::move(projectile));

                                    (Un std::unique_ptr n'est pas copiable. Sinon, il ne serait pas unique).

                                    HS : utilises std::make_unique au lieu de new si tu peux.

                                    HS2 : Pourquoi std::list et pas std::vector ?

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      23 juin 2017 à 16:59:28

                                      Ok donc en utilisant std::move cela fonctionne par contre j'ai toujours le problème du getAnimation.

                                      HS : utilises std::make_unique au lieu de new si tu peux.

                                      J'ai vu que std::make_unique est uniquement dispo pour C++14 or je suis sous c++11 donc je sais pas si ca vaut le coup de faire la transition pour ça.

                                      HS2 : Pourquoi std::list et pas std::vector ? 

                                      D'après ce que j'ai lu dans divers tutoriel, une liste permet de stocker plus efficacement les nombreux projectiles du jeu et surtout de mieux gérer la suppression d'élément de la liste. Après je débute en C++ donc je ne sais pas trop si c'est juste :)

                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        23 juin 2017 à 17:15:30

                                        joezzz a écrit:

                                        Ok donc en utilisant std::move cela fonctionne par contre j'ai toujours le problème du getAnimation.

                                        HS : utilises std::make_unique au lieu de new si tu peux.

                                        J'ai vu que std::make_unique est uniquement dispo pour C++14 or je suis sous c++11 donc je sais pas si ca vaut le coup de faire la transition pour ça.

                                        HS2 : Pourquoi std::list et pas std::vector ? 

                                        D'après ce que j'ai lu dans divers tutoriel, une liste permet de stocker plus efficacement les nombreux projectiles du jeu et surtout de mieux gérer la suppression d'élément de la liste. Après je débute en C++ donc je ne sais pas trop si c'est juste :)

                                        • Il n'y a aucun intérêt à rester en C++11 si on a un compilateur qui permet d'utiliser C++14.
                                        • Souvent les arguments donnés pour expliquer que les listes chainées sont "plus efficaces" que les vecteurs ne tiennent absolument pas la route.

                                        Dans un jeu de ce genre, la collection de projectiles doit être parcourue de long en large plusieurs dizaines de fois par seconde, parce qu'il faut bien les afficher. Dans le même temps, il ne va y avoir que quelques collisions, et il n'y a pas des milliers de projectiles : dans un vecteur, il ne s'agira que de décaler quelques pointeurs dans un tableau. Alors qu'avec une liste chainée, à chaque ajout/retrait on va faire des allocations/libérations dynamiques des "maillons" de la chaine, en plus de la construction/destruction des projectiles.

                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          23 juin 2017 à 19:18:26

                                          En faite je pense que la liste est plus intéressante car il n'y a justement pas tout le décalage a faire lors de la suppression d'un element. En plus niveau taille, la liste est plus intéressante car on peut y stocker plus d'élément.

                                          Après c'est vrai que je pense avoir au maximum 1000 projectiles dans mon jeu au même moment donc je ne sais pas trop si c'est plus interessant d'utiliser les listes plutôt que les vecteurs dans ce cas là.

                                          -
                                          Edité par joezzz 23 juin 2017 à 19:19:00

                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            23 juin 2017 à 19:25:34

                                            En général, l'argument de la liste chaînée vs un tableau est basée sur la complexité algorithmique, qui est effectivement meilleure pour les listes pour inserer/supprimer.

                                            Mais c'est oublier que la complexité algo n'est qu'un outil théorique pour estimer le comportement d'un algo en fonction de la taille des données. Il y a beaucoup d'autres paramètres à prendre en compte en pratique, en particulier (ce qui est critique ici) la gestion de la mémoire et des caches.

                                            Par défaut, tu peux en général utiliser un tableau. Si tu veux autre chose, c'est de l'optimisation et c'est préférable de faire du profiling pour savoir ce qui est le mieux de faire.

                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              23 juin 2017 à 20:10:20

                                              La complexité algorithmique, à qui je présente mes plus profonds respects, ça cause de ce qui se passe symptotiquement, quand la taille des données tend vers l'infini..

                                              Reste à voir si, dans le contexte où on programme, on se situe plutot du côté 0 ou du celui de l'infini. Lequel peut être assez loin. Par exemple, il faut un certain nombre d'éléments pour qu'un algorithme "optimal" de tri en n.log(n) soit en pratique plus avantageux qu'un bête tri par insertion, quadratique. A vos benchmarks !

                                              Pour la taille de la liste, ne pas oublier qu'on va avoir pour chaque élement, qui sera un pointeur dans ce cas, il y aura au moins un pointeur sur le suivant, voire sur le précédent, et que tout ça sera un bloc alloué dynamiquement dont la taille sera arrondie à un multiple de je ne sais plus combien.

                                              Pour les économies de place, vous pouvez repasser. Pour la localité en mémoire, qui a un effet important sur les perfomances, pareil.

                                               L'optimisation, c'est de regarder quelles parties du code bouffent le plus de temps, de développer un remplacement, et de tester pour voir lequel est vraiment mieux. Pour l'estimation au pif, on est très mauvais.

                                              -
                                              Edité par michelbillaud 23 juin 2017 à 20:15:31

                                              • Partager sur Facebook
                                              • Partager sur Twitter

                                              Objets en C++

                                              × 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