IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage C++ Discussion :

Gros soucis de compréhension du polymorphisme


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2010
    Messages
    33
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2010
    Messages : 33
    Par défaut Gros soucis de compréhension du polymorphisme
    Bonjour,

    La question que je vais poser ici est basique, mais le fait est que je n'arrive pas à y trouver de réponse. Je n'arrive pas à saisir comment utiliser le correctement polymorphisme.

    Je prends un exemple très simple pour illustrer mon problème :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    class Transformable
    {
    protected :
       float   pos_x;
       float   pos_y;
       float   rotation;
    };
     
    class Player : public Transformable
    {
    public :
       void   set_name( const std::string& name );
    protected :
       std::string   name;
    };
     
    class Building : public Transformable
    {
    public :
       void   open_door( void );
    protected :
       bool   is_door_open;
    };
    Imaginons que je veuille faire un jeu, qui contiendrait de nombreux objets différents ayant tous leurs propres spécificités ainsi que certains points en commun (des joueurs, des arbres, des armes...). Si je les stocke par polymorphisme sur un pointeur, comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    std::list< Transformable* >   object_list;
     
    object_list.push_back( new ( Player ) );
    object_list.push_back( new ( Player ) );
    Tous mes objets sont stockés dans la même liste, mais je perds l'accès aux méthodes des classes filles de Transformable. Je sais bien qu'il est possible d'employer des virtuelles pures pour surplanter des méthodes de la classe mère, mais imaginons que mes classes filles possèdent certaines méthodes qui leur sont propres. Il y a possibilité de downcaster, mais j'ai lu que c'était à éviter car crado. Pour contourner le problème, je pourrais stocker mes objets par catégorie :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    std::list< Player* >     players_list;
    std::list< Building* >   buildings_list;
    Sauf que ça me paraît franchement sale, surtout si il y a beaucoup d'objets différents et que les listes se multiplient.

    Du coup, j'en arrive à ma question : Comment stocker mes objets de la manière la plus générique possible sans pour autant perdre des méthodes au passage? Quelle est la manière idéale de faire cela en C++?

    Merci d'avance.

  2. #2
    Invité
    Invité(e)
    Par défaut
    Sauf que ça me paraît franchement sale, surtout si il y a beaucoup d'objets différents et que les listes se multiplient.
    Tu peux toujours utiliser une map, avec en clé le type de l'objet.

    Sinon, pour ton cas tu as le dynamic_cast, et ca me choque pas plus que ca, seulement tu risques de voir des choses gênantes du style:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    for iterator in obj_list
    if iterator is typeof player
    else if iterator is typeof building
    ...
    ce qui est peut etre pas l'idéal.

    Rien ne t'empêche de préserver l'héritage, mais un autre conteneur est probablement plus adapté.

  3. #3
    Membre Expert Avatar de Trademark
    Profil pro
    Inscrit en
    Février 2009
    Messages
    762
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2009
    Messages : 762
    Par défaut
    Si tu cherches à mettre des arbres avec des humains, ça va certainement poser problème. Pourquoi ? Simplement parce que ces deux "objets" n'ont pas les mêmes fonctionnalités et traitements.

    Le polymorphisme, c'est pas fait pour ranger des objets dans un même container pcq t'as la flemme de créer des classes en plus. C'est fait pour pouvoir effectuer des traitements qui ont la même fonction, mais qui ne s'effectue pas de la même façon. Par exemple si dans ton jeu, il y a une ferme avec plein d'animaux, alors tu peux faire un héritage pour tous les animaux qui crient, par conséquent tu pourras appeler la méthode "crie()", sur tous les animaux, sans pour autant savoir quel est l'animal qui crie.

    En bref, réfléchis aux objets qui font la même chose, pour que tu puisses factoriser certains traitements.

    D'un autre côté, je vois qui tu fais un héritage sur "Transformable", qui n'a que modérément sa place ici. Dans ce cas, j'aurais plutôt tendance à privilégier la composition, car tu ne peux pas dire qu'un building EST-UNE matrice de transformation. Par contre, tu peux dire qu'un building A-UNE transformation, ce qui d'or et déjà beaucoup plus logique.

    De toutes façons, il faut que tu poses ton clavier, et prenne un crayon pour modéliser ton programme sur PAPIER. Apprend l'UML si tu ne sais pas comment faire.

    Finalement, je finirai pour un petit conseil à part, n'utilise pas des std::list parce que tu dis "des listes d'objets". Utilise des vectors. Je te laisse chercher les raisons sur le forum ou web, on en a déjà assez parlé.

  4. #4
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Pourquoi vouloir mettre tous ces objets dans une liste ? Une réponse pourrait être : Pour les afficher, il faut bien que le moteur graphique connaisse l'ensemble des objets, quels que soit leur nature.

    Certes. Dans ce cas, le type de base ne serait probablement pas Transformable mais Displayable, ou GraphicalObject, ou que sais-je encore. Et ce qui serait important dans ce cas là serait plus la méthode virtuelle Display.

    Maintenant, certains de ces objets sont des personnage, et possèdent des méthodes spéciales connues de l'IA, par exemple, et que d'autres sont juste des obstacles utilisés par l'algorithme de calcul de chemin. Le plus simple est alors de créer dans ces parties du code des listes(*) du bon type. L'IA aurait une liste de personnages (qui est peut-être une classe de base), et l'algo de calcul une liste d'obstacles, ou encore une matrice de dimension 2 ou 3 avec des obstacles, ou toute autre structure de données qui va bien pour cet algorithme.

    Comment faire le lien avec le fait que personnage, obstacle et graphical object sont trois aspects d'un même objet ? Il y a plusieurs solutions. On peut imaginer par exemple qu'un monstre hérite de GraphicalObject, de Personnage, et éventuellement d'obstacle, selon le style du jeu. Ou on peut imaginer qu'un personnage possède une représentation graphique.

    Dans tous les cas, il va falloir assurer une certaine cohérence entre ces différents aspects. Quand l'IA décide qu'un personnage avance, sa représentation graphique doit changer de position, et le système de calcul de chemin doit vider une case et en remplir une autre, par exemple.



    (*) list est ssouvent égal à std::vector en c++
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Dans ces cas là, je fais des listes/vecteurs/maps de pointeurs, par catégorie. Et si j'ai besoin de faire des traitements génériques, je rajoute une liste qui contient les pointeurs vers tous les éléments concernés. Peu importe si le pointeur d'un même élément est stocké dans deux structures de données différentes. Ça ne coûte rien, de stocker/chercher un pointeur.

    Quant à savoir comment ajouter les fonctionnalités de Transformable, je préconiserais quant à moi l'héritage privé, avec éventuellement du CRTP.

  6. #6
    Membre Expert

    Avatar de germinolegrand
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Octobre 2010
    Messages
    738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2010
    Messages : 738
    Par défaut
    std::set pour stocker les pointeurs est souvent approprié. (std::map selon le cas, mais plus rare).

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. interface à concevoir toute simple et gros soucis
    Par skystef dans le forum AWT/Swing
    Réponses: 7
    Dernier message: 02/02/2006, 16h31
  2. [Visual Studio 2003] J'ai un très gros souci !
    Par bart64 dans le forum EDI/Outils
    Réponses: 2
    Dernier message: 18/11/2005, 15h01
  3. [C#][Visual C# Express] Gros souci avec Excel
    Par poullos dans le forum EDI/Outils
    Réponses: 7
    Dernier message: 18/11/2005, 13h15
  4. Petit soucis de compréhension
    Par AlexB59 dans le forum Langage SQL
    Réponses: 3
    Dernier message: 26/10/2005, 10h18
  5. Gros soucis avec pgaccess et postgresql
    Par Missvan dans le forum PostgreSQL
    Réponses: 9
    Dernier message: 13/04/2004, 16h16

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo