Partage
  • Partager sur Facebook
  • Partager sur Twitter

Problème sur les pointeurs

Matrice & cie...

    3 avril 2008 à 22:13:38

    Bonsoir à tous ! :)

    Après plus d'un an sans toucher à du C++, je reviens dessus.
    Seulement, après avoir fait uniquement du Java, il y a quelques automatismes qui ne reviennent pas... :(
    Mon problème concerne les pointeurs et l'allocation dynamique (autant dire tous les plus gros trucs difficiles en C++)...

    Ce dernier est le suivant :

    J'ai créé une classe Grille qui contient qui contient une matrice d'un objet Case.
    A chaque fois que j'ai une méthode de Grille en relation avec une matrice (notamment setMatrice, ou constructeur paramétré), eh bien je ne sais pas comment m'y prendre...

    Voici mes questions :
    1. Est-ce que cette signature de Grille est bonne ? Elle permet, à partir de changer la matrice d'une Grille.
    1. void setCases(Case **c)


    2. Comment déclarer une matrice de Case (qui prend deux paramètres entiers) et ensuite la désigner lors de l'appel au constructeur paramétré de Grille ?


    En espérant que j'ai été assez clair, merci d'avance pour votre aide ! ;)

    • Partager sur Facebook
    • Partager sur Twitter
      3 avril 2008 à 23:37:25

      Utilises des classes déjà toutes faites -> boost.multi_array dans ton cas (ou un vecteur de vecteur, mais c'est un chouilla bancal pour une structurée "carrée") -- l'allocation dynamique en C++ peut être très facile ... souvent il y a moyen de ne pas en faire directement.

      Sinon, regarde la FAQ C++ de développez.

      PS: une classe Grille qui dispose d'une fonction setMatrice ressemble pour moi à une abération -- j'ai horreur des mutateurs, surtout quand ils attaquent directement la structure interne des objets.
      • Partager sur Facebook
      • Partager sur Twitter
      C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
        4 avril 2008 à 13:29:30

        Merci beaucoup pour ta réponse ! :)
        Concernant la solution que tu me proposes, à savoir passer par une classe toute faite, je préfère m'en passer car l'application que je développe est vraiment faite pour me faire retrouver les bases du C++, donc je préfère affronter le problème en face vois-tu ! ^^

        Notamment, j'aimerais savoir pourquoi quelque chose comme cela ne fonctionne pas ?

        1. Case** grille = new Case*[5];
        2. for (int i=0; i<5; i++)
        3.         grille[i] = new Case[5];
        4. for (int i=0; i<5: i++)
        5.         for (int j=0; j<5; j++)
        6.                 grille[i][j] = Case(0, 0);


        C'est la déclaration de matrice que je trouve un peu partout (net, bouquins...), mais Visual Studio me fait une belle erreur en me disant que mes for constituent une erreur de syntaxe... Mais évidemment ils sont justes donc l'erreur provient de la matrice elle-même (à savoir que mon constructeur paramétré de Case(int a, int b) est correct)... :(

        Qu'ai-je fait de faux ?

        Par contre je ne comprends pas en quoi mon mutateur serait une aberration ; comme j'ai pu l'apprendre, en POO on protège les attributs en les mettant privé, et les classes extérieures ne peuvent y accéder que par accesseur/mutateur. Ma conception de la chose est-elle fausse ?


        Toujours merci d'avance à ceux qui me viendront en aide ! :)
        • Partager sur Facebook
        • Partager sur Twitter
          4 avril 2008 à 13:54:48

          VC6, c'est ça ? (si ta machine n'est pas trop vieille et que tu as une connexion au net autrement que par modem 56k, je ne peux que te conseiller d'abandonner ce compilo plus vieux que la norme qui aura très bientôt déjà 10ans ...)

          Sinon, ta seconde boucle ne sert à rien, fais en sorte que ton constructeur par défaut initialise comme il se doit.


          Des accesseurs/mutateurs.
          Si c'est pour donner accès à un détail d'implémentation, pourquoi le cacher ?
          Il faut savoir faire la différence entre une propriété (qui est exposée via accesseurs/mutateurs) et un attribut qui est un détail d'implémentation. Ce n'est pas parce que tu as un attribut que tu dois le considérer comme une propriété et vice-versa. Bien au contraire.
          Un des aspects importants en POO (et pas que), c'est de découpler tes classes. Si ta grille est en charge des cases, c'est par elle qu'il faut passer pour altérer chaque case. C'est pas aux autres de tout modifier comme des bourrins qui ne vérifient rien (cohérence des dimensions, etc)


          Bref. Définis toi une classe tableau2D (générique) (responsabilités: gérer la mémoire, cohérence des dimensions, et les accès []), définis ensuite ta grille comme un truc qui encapsule un Tableau2D<Case> (responsabilité propres à un grille des cases, ....), et construit ton jeu (?) par dessus.
          • Partager sur Facebook
          • Partager sur Twitter
          C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
            4 avril 2008 à 14:20:55

            Visual Studio 2005, ça commence à dater ouaip ! :p

            Mais à ce moment, comment fais-tu pour savoir ce qui doit être considéré comme une propriété ou non ?
            Pourrais-tu me fournir un exemple simple par exemple s'il-te-plaît ? J'ai un peu du mal à voir la nuance au premier abord...

            Si je n'ai pas créé une classe spéciale pour ma matrice, c'est que je pensais qu'il serait aisé de la manipuler ; mais maintenant que tu en parles ce sera certainement une très bonne idée ! ^^

            Et juste pour placer dans le contexte, ce serait pour créer une sorte de T-RPG ; je pense déléguer la création du niveau à la lecture par fichier. Penses-tu que pour créer la grille ce serait alors judicieux de, par exemple, faire un constructeur pour le Tableau2D<Case> avec un nom de fichier en paramètre pour qu'il remplisse les cases de lui-même ? Ou vois-tu une meilleure solution ?


            En tout cas, tes conseils me sont bénéfiques, merci beaucoup ! :)
            • Partager sur Facebook
            • Partager sur Twitter
              4 avril 2008 à 14:59:39

              Citation : Felar

              Visual Studio 2005, ça commence à dater ouaip ! :p



              Seulement 3 ans, si tu avais dis Visual C++ 6.0 ou .NET 2002/2003. Ça c'est vieux!

              Citation : Felar

              Mais à ce moment, comment fais-tu pour savoir ce qui doit être considéré comme une propriété ou non ?
              Pourrais-tu me fournir un exemple simple par exemple s'il-te-plaît ? J'ai un peu du mal à voir la nuance au premier abord...

              Si je n'ai pas créé une classe spéciale pour ma matrice, c'est que je pensais qu'il serait aisé de la manipuler ; mais maintenant que tu en parles ce sera certainement une très bonne idée ! ^^



              I wish! Bien sur, si tu veux penser en C++ il faut penser classe. Mais pas n'importe comment. Penses en classes opaques, c'est à dire des classes qui fonctionnent par elles-mêmes et qui ne permettent pas l'accès à leurs données de bases directement. Si le but est de faire une Matrice pour une carte et non au sens mathématique alors développe un classe Carte qui sera capable de te fournir toutes les opérations dont tu as besoin.


              Citation : Felar

              Et juste pour placer dans le contexte, ce serait pour créer une sorte de T-RPG ; je pense déléguer la création du niveau à la lecture par fichier. Penses-tu que pour créer la grille ce serait alors judicieux de, par exemple, faire un constructeur pour le Tableau2D<Case> avec un nom de fichier en paramètre pour qu'il remplisse les cases de lui-même ? Ou vois-tu une meilleure solution ?


              En tout cas, tes conseils me sont bénéfiques, merci beaucoup ! :)



              Tableau2D<> peut contenir toutes les opérations de sur le tableau mais je te conseilles vivement de faire une classe qui comporte un Tableau2D<> (composer de) ex. Carte qui elle s'occupera des opération de lecture/écriture d'un fichier, les liens entre les cartes (lorsqu'on arrive sur telle case on est téléporter sur telle carte...), etc...

              Tableau2D<> peut parcontre avoir des fonctions de sérialization pour la transformer en données inscriptibles dans un fichier.


              Les idées ici sont des exemple pour t'encourager à créer des structure de classes. Il ne faut pas avoir peur d'en créer pour les projets qui peuvent en profiter. Ensuite tu es débarassé des opérations sur les structures de données on peut se concentrer sur la dynamique du projet sans avoir à revenir tout le temps sur la même chose ou les mêmes problèmes. Et en plus on se libère facilement des risque d'erreur une fois nos classes bien testées.
              • Partager sur Facebook
              • Partager sur Twitter
                4 avril 2008 à 15:06:29

                Citation : Felar

                a- Visual Studio 2005, ça commence à dater ouaip ! :p

                b- Mais à ce moment, comment fais-tu pour savoir ce qui doit être considéré comme une propriété ou non ?
                Pourrais-tu me fournir un exemple simple par exemple s'il-te-plaît ? J'ai un peu du mal à voir la nuance au premier abord...

                Si je n'ai pas créé une classe spéciale pour ma matrice, c'est que je pensais qu'il serait aisé de la manipuler ; mais maintenant que tu en parles ce sera certainement une très bonne idée ! ^^

                c- Et juste pour placer dans le contexte, ce serait pour créer une sorte de T-RPG ; je pense déléguer la création du niveau à la lecture par fichier. Penses-tu que pour créer la grille ce serait alors judicieux de, par exemple, faire un constructeur pour le Tableau2D<Case> avec un nom de fichier en paramètre pour qu'il remplisse les cases de lui-même ? Ou vois-tu une meilleure solution ?


                En tout cas, tes conseils me sont bénéfiques, merci beaucoup ! :)


                a- Mince alors, j'étais persuadé qu'ils avaient patché cette non conformité... :-/
                Il aurait fallu sorti la déclaration de i de tes for.
                Ou alors est-ce parce qu'il y a un ':' dans le second for ?

                b- L'expérience fait la différence.
                La recette de cuisine que j'emploie aujourd'hui est la suivante :
                (*) si je veux des accesseurs, je les rajoute au fur et à mesure (souvent pour des raisons de logs)

                (*)
                0- Tous mes constructeurs initialisent tous mes attributs à une valeur pertinente, qui met l'objet dans un état consistant : il est utilisable sans que j'ai à altérer un quelconque attribut par la suite
                1- par défaut, pas de mutateur
                2- Si j'ai besoin d'altérer l'état interne d'un attribut, j'essaie de voir si en fait, je ne pourrais pas donner un nom à cette action d'altération, si oui, j'en fais un verbe, et j'ai alors le nom d'une fonction dédiée. --
                en vrai, on réfléchit dans l'autre sens : on détermine les responsabilités des objets, on en fait des verbes, et on conclut par les attributs qui permettent de supporter ces responsabilités

                3- Si vraiment, j'ai 150 altérations différentes, je me pose la question de savoir si je n'ai pas foiré mon design quelques part
                4- Enfin, si je suis trop pressé, je fais sauter l'encapsulation: soit je donne l'accès direct, soit je mets en place un mutateur, le temps de pouvoir réfléchir plus sérieusement à la question

                Après, il y a le cas particulier des propriétés (une position que l'on peut forcer (bien qu'elle devrait être altérée par la vitesse et les contraintes de déplacement venant du terrain), un vêtement porté (et même là, un wear(), sera toujours mieux qu'un setClothes())). Comme les responsabilités, cela se détermine au moment du design.

                On retrouve une partie de tout ceci dans la FAQ de developpez.


                c- Le Tableau2D<>, sa responsabilité, c'est d'être un tableau et de s'occuper de se qui est propre à un tableau : contenir des éléments. Il encapsulera la gestion de la mémoire. Gardera la consistance entre dimension et nombre d'éléments
                La grille, est plus un objet dit métier. C'est à dire un truc en rapport à ton jeu. C'est la grille qui s'occupera de lire le fichier, qu'elle sait être un fichier de définition de cases. Pour faciliter sa mise en oeuvre, tu pourras utiliser un Tableau2D.

                (Là où je triche, c'est que je pousse à faire de Tableau2D une classe générique (template))
                • Partager sur Facebook
                • Partager sur Twitter
                C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                  4 avril 2008 à 15:27:14

                  Ok, je vois bien ce que vous voulez dire ; ça doit certainement être des réflexes qu'on ne peut acquérir qu'après pas mal de pratique ! :)

                  Quoi qu'il en soit, je vais tenter d'avancer mon projet en tenant compte de vos remarques constructives et si j'ai un problème je reviendrai poster un message ! ^^

                  Merci vraiment à vous deux !
                  • Partager sur Facebook
                  • Partager sur Twitter

                  Problème sur les pointeurs

                  × 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