Partage
  • Partager sur Facebook
  • Partager sur Twitter

Un tableau de "type de classe"

    5 octobre 2007 à 8:02:13

    Salut à tous
    Admettons que j'ai trois classe A , B et C. Est-ce possible (à l'aide des template ou autres) de stocker le type de ces classes dans un tableau ? (Du genre tableau[0] == A). Ou bien est-ce une idée stupide, auquel cas existe-t-il une alternative ?
    Merci
    • Partager sur Facebook
    • Partager sur Twitter
      5 octobre 2007 à 9:12:06

      Que veux-tu faire en vrai ?
      (pas la question théorique qui me parait bizarre, mais le problème de plus haut niveau que tu cherches à résoudre)
      • 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.
        5 octobre 2007 à 9:48:18

        Alors : tu ne peux pas stocker des types commes ça. ça c'est la mauvaise nouvelle.

        Mais tu as des astuces : tu veux stocker soit une classe A, soit B, soit C ?
        --> Fait les hériter toutes les 3 d'une classe mere M.

        1. class A:public M
        2. class B:public M
        3. class C:public M


        Ensuite, utilises le polymorphisme :


        1. M* tableau[50];
        2. tableau[0] = new A;
        3. tableau[1] = new C;
        4. tableau[2] = new B;



        Et l'inconvénient, avec le polymorphisme, c'est que tu perds le type d'entrée, mais ça, ça se contourne :

        1. enum type
        2. {
        3.    TYPE_CLASS_A,
        4.    TYPE_CLASS_B,
        5.    TYPE_CLASS_C,
        6. };
        7. class M
        8. {
        9. ...
        10.    virtual enum type GetType()=0;  // virtual pure
        11. };


        --> Implémentation obligatoire de GetType dans toutes les filles A,B,C du fait de la virtuelle pure.

        1. enum type A::GetType()
        2. {
        3.   return TYPE_CLASS_A;
        4. }
        5. enum type B::GetType()
        6. {
        7.   return TYPE_CLASS_B;
        8. }
        9. enum type C::GetType()
        10. {
        11.   return TYPE_CLASS_C;
        12. }


        Utilisation apres initialisation :

        1. if (tableau[0]->GetType == TYPE_CLASS_A)  // forme de M est A.
        2. {
        3.    A* a = static_cast<A*>(tableau[0]);  // downcasting
        4.    // ici, tu peux manipuler A
        5. }
        6. if (tableau[0]->GetType == TYPE_CLASS_B)  // forme de M est B.
        7. {
        8.    B* a = static_cast<B*>(tableau[0]);  // downcasting
        9.    // ici, tu peux manipuler B
        10. }
        11. ...

        • Partager sur Facebook
        • Partager sur Twitter

        Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

          5 octobre 2007 à 15:18:31

          "if (tableau[0]->GetType() == TYPE_CLASS_A)"

          Solution simple mais peu sécuritaire. Comme dirait lmghs : C'est du à une mauvaise conception.

          Mais déjà on touche au polymorphisme et c'est simple à comprendre et mettre en oeuvre... Si tu nous éclairait sur ton but absolu on pourrait te guider sur une bonne solution si meilleur solution que celle de Fvirtman il y a.

          Désolé Fvirtman ;) ce n'est pas pour dénigrer ton aide, je trouve ta solution bien en partie
          • Partager sur Facebook
          • Partager sur Twitter
            5 octobre 2007 à 15:19:50

            y'a pas de mal, je proposais UNE solution, et non LA solution :)
            • Partager sur Facebook
            • Partager sur Twitter

            Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

              5 octobre 2007 à 17:07:24

              Merci de vos réponses. Puisque vous me le demandez je vais vous expliquer mon problème.
              Voici un petit schéma :
              Image utilisateur
              Concrètement , A et B sont des classes abstraites (donc on ne peut pas les instancier, si je ne me trompe pas). Les classes 1,2 et 3 héritent de A, 4, 5 et 6 héritent de B.
              Je voudrais pouvoir instancier à ma guise un objet qui serait à la fois un héritier de A et un B. Concrètement je voudrais pouvoir crée un objet qui ait par exemple les proprietés de 1 et de 6, ou alors de 2 et de 3, ou n'importe quoi d'autre, mais il me semble qu'en C++ ça n'est pas possible directement. Faire des objets spécifiques héritant de chacun des couples me semble bien complexe (surtout qu'en réalité j'ai beaucoup plus que 6 classes).
              Et donc j'avais pensé qu'il y avait peut être quelque chose à faire avec les types de classe mais à la réflexion je ne voit pas trop comment je pourrais m'en sortir.
              • Partager sur Facebook
              • Partager sur Twitter
                5 octobre 2007 à 17:16:55

                bizarre ton affaire !

                Tu pourrais, par exemple, faire un std::pair<T,T2> si tu veux faire des couples. En template, ça pourrait t'aider. mais je trouve ton probleme bizarre.
                • Partager sur Facebook
                • Partager sur Twitter

                Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

                  5 octobre 2007 à 17:20:11

                  Tu veux une explication encore plus précise ?
                  • Partager sur Facebook
                  • Partager sur Twitter
                    5 octobre 2007 à 17:21:01

                    ben tu peux la donner, mais je ne suis pas sur de répondre tout de suite : faut que je parte la ! :)
                    • Partager sur Facebook
                    • Partager sur Twitter

                    Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

                      5 octobre 2007 à 17:37:47

                      Je me lance.
                      Je suis en train de penser comment réadapter TeamBuddies, un vieux jeu de playstation, pour PC. Pour faire très simple, il y a plusieurs équipes (les bleus, les jaunes etc) et dans chaque équipe il y a plusieurs types de personnages : les médecins, les ninjas, les commandos etc.
                      Chaque type de personnage a des particularités, et chaque équipe aussi : par exemple un ninja jaune frappe avec une force différente, se déplace à un vitesse différente et dit des choses différentes d'un medecin bleu, à cause de son type et à cause de sa couleur. Et je voudrais pouvoir instancier un ninja jaune ou un médecin bleu sans avoir à créer une classe NinjaJaune ou MedecinBleu.
                      • Partager sur Facebook
                      • Partager sur Twitter
                      Anonyme
                        5 octobre 2007 à 18:05:15

                        Moi je le verrai autrement :
                        Une classe Perso aurait deux attribut : type et couleur.
                        type serait construit (->constructeur) différemment suivant son type (ex : type t(NINJA); ) , idem pour couleur.
                        Comme ce ne sont que les attribut qui change de valeurs et pas le contenu de la classe, l'héritage ne me semble pas utile. Avis d'un pro pour me contredire ou m'"appuyer" (j'ai le mot qui convient mieux qui m'échappe*) SVP.

                        EDIT : je crois que plussoyer conviens. :-°
                        • Partager sur Facebook
                        • Partager sur Twitter
                        Anonyme
                          5 octobre 2007 à 18:08:02

                          Tu va quand même pas créer une classe ninje bleu , une classe ninja verte ... ?
                          OO.
                          Si oui , revoit toute ta conception.
                          Une agrégation avec un objet décrivant toute les caractéristiques de ton ninja serait bien mieu.
                          • Partager sur Facebook
                          • Partager sur Twitter
                            5 octobre 2007 à 18:14:50

                            Citation : hiura

                            Moi je le verrai autrement :
                            Une classe Perso aurait deux attribut : type et couleur.
                            type serait construit (->constructeur) différemment suivant son type (ex : type t(NINJA); ) , idem pour couleur.
                            Comme ce ne sont que les attribut qui change de valeurs et pas le contenu de la classe, l'héritage ne me semble pas utile. Avis d'un pro pour me contredire ou m'"appuyer" (j'ai le mot qui convient mieux qui m'échappe) SVP.



                            +1.
                            C'est comme ça que je ferais aussi.
                            • Partager sur Facebook
                            • Partager sur Twitter

                            Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

                              5 octobre 2007 à 21:49:58

                              je ferais moi un mélange : un classe de base pour IBuddies offrant toute les possibilité communes à chaque "Profession" de buddies. Puis des classe héritée : Ninja, Medecin, Commando.

                              je mettrerai les couleurs d'équipe dans un enum et à l'instanciation d'un Ninja tu lui passe sa couleur

                              c'est un mélange mais puisqu'un Ninja est très différent d'un Medecin mais pas si différent d'un Ninja d'une autre couleur je crois que ce sera moins de if et/ou switch à faire...

                              De plus si tout les personnages d'une équipe ont les mêmes avantages je ferais une classe Équipe qui permettrai de modifier simplement les attributs de mes personnages.
                              • Partager sur Facebook
                              • Partager sur Twitter
                                5 octobre 2007 à 22:20:03

                                Citation : Davidbrcz

                                Tu va quand même pas créer une classe ninje bleu , une classe ninja verte ... ?
                                OO.
                                Si oui , revoit toute ta conception.
                                Une agrégation avec un objet décrivant toute les caractéristiques de ton ninja serait bien mieu.


                                Non au contraire c'est ce que je chercher à éviter.
                                Mattex, Deux ninjas de couleurs différentes ont quand même quelques différences mis à part la couleur du modèle .
                                hiura, entre plusieurs professions il n'y a pas que les attributs qui changent, il y a aussi certaines méthodes (un medecin peut soigner, un ninja peut donner des coups de sabre pour reprendre mes exemples), je pense qu'il faut un héritage de ce coté là.
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  6 octobre 2007 à 0:06:48

                                  Alors polymorphisme comme je te disais dans mon post plus haut :)

                                  pour l'instant, ça peut etre une solution : avec une methode gettype() virtual pure dans la mere, et donc, quand on a besoin de spécifier, ça nous permet de faire un downcast.

                                  Cela dit, comme disais Matex, ce n'est peut etre pas la meilleure solution : je ne connais pas tous les design pattern, donc a toi de voir si cette solution te convient quand meme, ou alors voir si dans les posts suivants :)
                                  • Partager sur Facebook
                                  • Partager sur Twitter

                                  Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

                                  Anonyme
                                    6 octobre 2007 à 1:08:01

                                    Salut,

                                    j'interviendrai juste sur le design, je laisse l'aspect techique aux "gurus" du C++ ci present. La meilleure approche me semble etre celle de Mattex. Une classe de base "Joueur", des classes qui en heritent ("Medecin", "Commando", "Coupeur de citron"). Apres pour les equipes, et les details propres à chaques joueurs, si ca peut se regler à l'instanciation (genre tel medecin est dans l'equipe rouge), bah une enum avec un accesseur devrait faire l'affaire.

                                    Apres si ta problematique est plus complexe, du genre le medecin rouge fait ci et ca, le bleu fait autre chose tout en gardant la meme idée (genre les deux soignent mais avec des effets, des bonus, whatever differents), tu peux regarder du coté du pattern Strategy. Mais ne deploie pas des solutions comme ca, si les differences sont minimes et peuvent etre fixées au debut, ou alors n'ont pas vraiment d'impact sur les traitements (un joueur rouge ou bleu si les equipes ont les memes unités, y a pas vraiment besoin de ce genre de motif, vu qu'au dela de sa couleur le traitement est le meme).
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      6 octobre 2007 à 1:48:40

                                      Plusieurs choses.

                                      Quitte à faire du downcasting (parfois on en a vraiment besoin, bien que le néophyte tombe 90% du temps dans le piège de croire que c'est la solution à son problème -- oui, c'est juste pour faire mentir MatteX qui avait bien répondu :P), autant utiliser ce que le langage nous offre plutôt que de verser dans le NIH (wikipédia!).
                                      En l'occurrence, le RTTI qui va se concrétiser dans ce cas là avec des dynamic_cast<> qui sont bien plus efficaces qu'une solution manuelle.


                                      azmeuk, ce que tu cherches à faire est envisageable avec l'héritage multiple, mais il y a des pré-requis très importants à respecter
                                      - D'abord que couleurs et rôles apportent des choses suffisament orthogonales, ou carrément prévues pour s'emboiter (on se rapproche des notions de politiques développées par Andrei Alexandrescu dans son Modern C++ Design ; je ne sais plus si Alp n'avait pas écrit des choses à ce sujet)

                                      - Ensuite, il ne doit pas y avoir d'évolution dynamique de ce que l'on est (pas de changement de couleur/role en cours d'exécution). C'est pour cette exacte raison que je tends à critiquer les modélisations de JdR où classes (de perso) et races sont des classes (OO) dont on hérite. Car cela ne permet ni le multiclassage, ni les pouvoirs de métamorphose.



                                      L'approche par attribut me parait préférable pour l'aspect dynamique. Chaque attribut représente un trait qui est spécialisable (héritage). Par déssus, tu as une classe englobante qui délégue à chacun de ses attributs spécialisés ce qui doit être fait.


                                      Sinon, avec l'héritage multiple, on arrive aux mêmes choses. On peut même sortir les templates (cf donc les ouvrages qui traitent de policies)
                                      1. class ICharacter : boost::noncopyable
                                      2. {
                                      3. public:
                                      4.    virtual ~ICharacter() {}
                                      5.    virtual void takeDamages(Damage const& dmg) = 0;
                                      6.    virtual void doSpecial(ICharacter & friendOrFoe) = 0;
                                      7. };
                                      8. template <class ColourPolicy, class RolePolicy>
                                      9. class CharacterImpl
                                      10. : public ICharacter
                                      11. , private ColourPolicy, private RolePolicy
                                      12. {
                                      13. public:
                                      14.     Character(.....) : ColourPolicy(...), RolePolicy(...) {}
                                      15.     virtual void takeDamages(Damage const& dmg) {
                                      16.        const Damage dmg2 = RolePolicy::applyImmunities(dmg); // immunités de classes
                                      17.        this->m_pv -= dmg2.howMany();
                                      18.     }
                                      19.     virtual doSpecial(ICharacter & friendOrFoe) {
                                      20.         const bool isFriend = this->testIfFriend(friendOrFoe);
                                      21.         const Damage dmg = (isFriend)
                                      22.             ? RolePolicy::specialForFoes()
                                      23.             : RolePolicy::specialForFriends();
                                      24.         friendOrFoe . takeDamage(dmg);
                                      25.     }
                                      26. private:
                                      27.     bool testIfFriend(ICharacter const& friendOrFoe) const {
                                      28.         // c'est un des cas où le downcastng est acceptable
                                      29.         // -- sinon, il faut sortir le DP visiteur pour faire du
                                      30.         // du /double dispatch/
                                      31.         ColourPolicy const * theFriend = dynamic_cast<ColourPolicy*>(&friendOrFoe);
                                      32.         // Je suppose que colueur == équipe, sinon, faire autrement
                                      33.         const bool isFriend = theFriend != 0;
                                      34.         return isFriend;
                                      35.     }
                                      36. };
                                      37. ...
                                      38. // ici, 150 typedefs
                                      39. typedef CharacterImpl<Blue, Ninja> BlueNinja ;
                                      40. // et c'est même possible de faire des spécialisations
                                      41. // plus précises reposant sur ce shéma.

                                      Bon. C'est très succint, et très vite et mal pondu. C'est juste pour donner une idée, d'autant que j'ai très certainement brulé des étapes, et que je doute que cela corresponde à ton jeu. Une petite enclume des familles quoi.
                                      La grosse difficulté de cette approche à politiques, c'est de bien définir chacun des traitements possibles, et comment les politiques interagissent au niveau le plus générique.

                                      En fait je crains assez que tu aies besoin du double-dispatch, et donc de faire des trucs plus cradingues à base de dynamic_cast (ou de visiteurs).
                                      Ou alors. Ou alors.

                                      Partir sur une solution que chaque Couleur/Rôle donne un ensemble d'actions possibles. Que chaque perso aie une action courante choisie à un instant t. Et que c'est cette action qui détermine l'interaction avec un autre perso. Ce qui permet de tirer sur des alliés, de soigner des énemis, etc.
                                      A y réfléchir, cela me parait plus simple, et plus souple.
                                      • 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.
                                      Anonyme
                                        6 octobre 2007 à 13:07:36

                                        Citation : azmeuk

                                        hiura, entre plusieurs professions il n'y a pas que les attributs qui changent, il y a aussi certaines méthodes (un medecin peut soigner, un ninja peut donner des coups de sabre pour reprendre mes exemples), je pense qu'il faut un héritage de ce coté là.


                                        Bien sûr il y a des limite avec ma "technique", mais pour ton exemple d'attaques et de soins, c'est faisable : dégâts > 0, soins < 0.

                                        Est-ce que une technique est meilleur qu'un autre ? Cela ne dépends pas que de la théorie ; la mise en place à surement un plus grand impacte.
                                        A toi de voir avec la-quelle tu es le plus à l'aise.
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          7 octobre 2007 à 11:58:56

                                          lmghs c'est ça que je cherchais merci beaucoup
                                          Et merci à tous les autres pour vos réponses, ça m'a permi de remettre un peu en cause ma conception.

                                          edit: Peu être une dernière question. Comment modèliser la solution de lmghs en UML ?
                                          • Partager sur Facebook
                                          • Partager sur Twitter

                                          Un tableau de "type de classe"

                                          × 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