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

 C++ Discussion :

[C++] Héritage, classes et tableaux


Sujet :

C++

  1. #1
    Expert confirmé
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Points : 4 388
    Points
    4 388
    Par défaut [C++] Héritage, classes et tableaux
    Bonjour à tous,

    Dans le cadre de mon programme, j'ai crée une classe ennemie mère et 2 classes filles qui hérite de la classe ennemie :
    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
     
    // classe mère
    class ennemie()
    {
       // attribues et contructeurs
    };
     
    // classes filles
    class guerrier : public ennemie
    {
          // attribues et contructeurs    
    };
    class magicien : public ennemie
    {
          // attribues et contructeurs    
    };
    Jusqu'à la tout va bien

    Maintenant j'ai créé un tableau d'ennemies grave au template vector :
    Puis j'ai ajouté un magicien et un guerrier :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    tab.puish_back(new guerrier());
    tab.push_back(new magicien());
    Maintenant je décide de récupéré le premier élément de mon tableau :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ennemie* toto = tab[0];
    Et là je suis coincé !

    Comment savoir si cet ennemie est un guerrier ou un magicien ?

    En effet, j'ai besoin d'accéder aux fonctions spécifiques des classes filles en fonction du type d'ennemies...

    Comment faire ?

    Merci
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  2. #2
    Membre chevronné
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Points : 1 921
    Points
    1 921
    Par défaut
    Citation Envoyé par Aspic Voir le message
    En effet, j'ai besoin d'accéder aux fonctions spécifiques des classes filles en fonction du type d'ennemies...
    Tu ne devrais pas avoir à faire ce test. Revoir ton design me parait de mise.
    Sinon, si t'aime le crados : dynamic_cast

  3. #3
    Expert confirmé
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Points : 4 388
    Points
    4 388
    Par défaut
    Citation Envoyé par Joel F Voir le message
    Tu ne devrais pas avoir à faire ce test. Revoir ton design me parait de mise.
    Sinon, si t'aime le crados : dynamic_cast
    Mince, comment dois je m'y prendre pour stocker tous mes types d'ennemies dans un unique tableaux et activer les "effets spécifiques" à chaque ennemies ?

    En gros, comment faire un "'SI ennemie dans mon tableau est de type GUERRIER alors frapper() SINON SI il est de type MAGICIEN alors lancerBouleDeFeu() ..."

    PS : J'aime pas le crados mais de toute manière ca ne marcherais pas car guerrier hérite de ennemie donc un guerrier* toto2 = dynamic_cast<guerrier*> (toto); plante ^^
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  4. #4
    Membre actif

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Points : 206
    Points
    206
    Par défaut
    Des fonctions virtuelles ?

    virtual void DoAction()=0; dans ennemies.hpp résoudrait tes problèmes.

  5. #5
    Expert confirmé
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Points : 4 388
    Points
    4 388
    Par défaut
    Citation Envoyé par NoIdea Voir le message
    Des fonctions virtuelles ?

    virtual void DoAction()=0; dans ennemies.hpp résoudrait tes problèmes.
    Mais je vais pas coder toutes les fonctions spécifique à un type d'ennemie en virtual dans la classe ennemie ? (Ex : virtual void lancerBouleFeu() dans ennemie.cpp n'a pas de sens car seul certains type d'ennemies peuvent faire cette action...

    Ou alors j'ai mal compris
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  6. #6
    Membre actif

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Points : 206
    Points
    206
    Par défaut
    Une fois que tes objets sont dans le même vecteur, il faut les traité de manière identique :
    Si par exemple attaquer pour un guerrier, c'est frapper et que pour un magicien c'est lancer une boule de feu, alors il faut implémenter virtual void Attaquer() dans ennemies.
    Pour se défendre, le magicien va peut-être fuir et le guerrier utiliser son bouclier donc, virtual void SeDefendre().
    Il ne devrait pas il y avoir tant de fonction à implémenter que sa...
    Si tu nous en disais plus.

  7. #7
    Expert confirmé
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Points : 4 388
    Points
    4 388
    Par défaut
    Ah je crois que j'ai compris,
    Donc en gros, je code une fonction Attaquer() non virtuelle dans chaque classe fille qui hérite de ennemie et dans ennemie je déclare : virtual void Attaquer()=0;

    Quand je vais parcourir mon tableau d'ennemies, dès qu'il tombe sur un guerrier, il appellera la fonction Attaquer() du guerrier etc.

    C'est bien ca ?

    PS : Le compilateur semble vouloir tranformer le destructeur de ma classe mère :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    t_ennemie::~t_ennemie() {}
    en
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    virtual t_ennemie::~t_ennemie()
    Pourquoi ?

    Merci
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  8. #8
    Membre actif

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Points : 206
    Points
    206
    Par défaut
    Parce que souvent, il y a une libération de mémoire différente. Si les destructeurs sont strictement identique dans guerrier et magicien, tu peux ignorer cet avertissement.

  9. #9
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    @NoIdea: La bonne répons est : parce que sinon c'est un comportement indéfini dans certains cas d'utilisation (libération à travers un pointeur de classe mère si l'objet est de type fille), et il n'y a PAS d'exception. Même si il est vraie qu'avec la plupart des compilo si le destructeur ne change pas ca ne pose pas de problème, mais ca reste du C++ crade.

    @OP: Oui c'est ca, ca s'appelle le polymorphisme. Si comme tu le disais au début tes fonction ne peuvent pas avoir de nom commun c'est qu'il n'est surment pas judiscieux de les faire cohabiter dans un conteneur, ou qu'il faut passer par des design plus évolué (cf visiteur).

  10. #10
    Membre actif

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Points : 206
    Points
    206
    Par défaut
    c'est un comportement indéfini dans certains cas d'utilisation (libération à travers un pointeur de classe mère si l'objet est de type fille), et il n'y a PAS d'exception.
    Ceci me surprend beaucoup. C'est tout de même pas valable lorsqu'il s'agit du destructeur par défaut ?!
    J'en profite pour dire que j'ai toujours fait comme sa et je n'ai jamais eut de problème, cependant, je le ferais dorénavant.

  11. #11
    Expert confirmé
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Points : 4 388
    Points
    4 388
    Par défaut
    Citation Envoyé par Flob90 Voir le message
    @OP: Oui c'est ca, ca s'appelle le polymorphisme. Si comme tu le disais au début tes fonction ne peuvent pas avoir de nom commun c'est qu'il n'est surment pas judiscieux de les faire cohabiter dans un conteneur, ou qu'il faut passer par des design plus évolué (cf visiteur).
    Oui c'est clair et net que certaines fonctions (je dis bien certaines) ne peuvent pas cohabiter dans la classe mère d'où mon idée de l'héritage et de créer une classe fille par type de monstre possible dans mon jeu.

    Ensuite tout stocker dans un vector n'est peut être pas une bonne idée mais ca simplifie grandement les choses quand je parcours mes ennemies non ? Car sinon je dois créer X tableaux d'ennemies avec X correspondant au type d'ennemies possibles puis après pour les parcourir je dois parcourir X tableaux, c'est pas la solution si ?
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  12. #12
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    In the first alternative (delete object), if the static type of the object to be deleted is different from its dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the static type shall have a virtual destructor or the behavior is undefined.
    Section 5.3.5

    C'est toujours vraie, et si tu augmente ton niveau d'alerte ton compilo devrait te le signler. Ca ne pose en gééral pas de problème car les compilos décide souvent d'implémenter le comportement comme ceci, mais on peut envisager qu'un compilateur décide que ca fasse tout autre chose.

    Tout stocker et le parcourir permet d'appeler une fonction dont le nom ne change pas sur toutes tes entités, si ce que tu veus faire est d'appeler une fonction dont le nom change (et que tu n'arrives pas à trovuer un nom commun), alors là ce n'est pas la solution.

    Dans ton cas tu as réussi à trouver un nom commun (qui a du sens évidament), donc c'est une solution viable.

    A coté de cette fonction il peut bien évidament il y avoir des fonction spécifique à chaque classe, mais elles ne seront pas utilisables depuis le conteneur.

  13. #13
    Expert confirmé
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Points : 4 388
    Points
    4 388
    Par défaut
    Citation Envoyé par Flob90 Voir le message
    Dans ton cas tu as réussi à trouver un nom commun (qui a du sens évidament), donc c'est une solution viable.
    Oui, le nom ne change pas c'est ce qu'il y a dans la fonction qui chagne en fonction des ennemies

    Citation Envoyé par Flob90 Voir le message
    A coté de cette fonction il peut bien évidament il y avoir des fonction spécifique à chaque classe, mais elles ne seront pas utilisables depuis le conteneur.
    Parfait c'est ce que je voulais savoir

    Merci à tous pour votre aide
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  14. #14
    Membre actif

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Points : 206
    Points
    206
    Par défaut
    In the first alternative (delete object), if the static type of the object to be deleted is different from its dynamic type, the static type shall be a base class of the dynamic type of the object to be deleted and the static type shall have a virtual destructor or the behavior is undefined.
    Merci de me l'avoir rappelé. Je suis surpris que g++ ne me dise rien (je suis en Wall et en pendantic) mais bon...peut être qu'il pense que je ne vais pas utiliser cette classe a partir d'un conteneur.

  15. #15
    Expert confirmé
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Points : 4 388
    Points
    4 388
    Par défaut
    Citation Envoyé par NoIdea Voir le message
    Merci de me l'avoir rappelé. Je suis surpris que g++ ne me dise rien (je suis en Wall et en pendantic) mais bon...peut être qu'il pense que je ne vais pas utiliser cette classe a partir d'un conteneur.
    Je suis en Wall aussi avec mingw et j'ai bien les warning
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  16. #16
    Membre actif

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Points : 206
    Points
    206
    Par défaut
    c++0x doit changer quelque chose ? J'utilise gcc Mingw 4.5... avec Codeblocks 8.02

  17. #17
    Expert confirmé
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Points : 4 388
    Points
    4 388
    Par défaut
    J'utilise aussi Codeblocks 8.02 bizarre...
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  18. #18
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    -Wnon-virtual-dtor pour activer ce warning, mais c'est mieux de la savoir, car ce warning alerte dès que tu as un héritage publique avec un destructeur non virtuel, ce qui n'est pas la règle exact. Par exemple un destructeur privé dans la classe mère assure qu'il n'y aura jamais de comportement invalide (cf classe de politique par exemple), mais ce warning alerte quand même dans ce cas là il me semble.

  19. #19
    Expert confirmé
    Avatar de Aspic
    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2005
    Messages
    3 905
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 3 905
    Points : 4 388
    Points
    4 388
    Par défaut
    Au fait juste une dernière question sur le polymorphisme, si par hasard dans ma méthode virtual Attaquer(), j'ai besoin d'avoir un paramètre de plus dans l'une des classes filles, suis je obliger de le faire passer dans Attaquer() sachant qu'il ne sera utilisé que par une seule classe fille ?

    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    // toujours dans le cadre de mes persos : guerrier et magicien
    void virtual attaquer(int puissanceFeu);
     
    // le paramètre puissanceFeu servira uniquement pour le magicien mais pas pour le guerrier
    A mon avis c'est pas possible de faire ca...

    Mais y'a t-il une solution ?
    Qui ne tente rien n'a rien !
    Ce qui ne nous tue pas nous rends plus fort !!
    Mon projet ZELDA en C++/Allegro
    http://www.tutoworld.com - Le Forum -
    Mes ressources Dotnet (cours, sources, tutos)
    --------------------------------------------
    + + =

    Ne pas oublier le Tag !

  20. #20
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 360
    Points : 23 600
    Points
    23 600
    Par défaut
    Citation Envoyé par Aspic Voir le message
    Au fait juste une dernière question sur le polymorphisme, si par hasard dans ma méthode virtual Attaquer(), j'ai besoin d'avoir un paramètre de plus dans l'une des classes filles, suis je obliger de le faire passer dans Attaquer() sachant qu'il ne sera utilisé que par une seule classe fille ?
    Si tu as un paramètre de plus dans la signature de ta fonction, ce sera considéré comme de la surcharge, et les deux « versions » seront considérées comme deux fonctions différentes, sauf si tu mets d'emblée tous les paramètres mais que tu précises une valeur par défaut pour le dernier, ce qui le rend optionnel.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 3 123 DernièreDernière

Discussions similaires

  1. problème (héritage || class || constructeur )?
    Par crazy_inf dans le forum C++
    Réponses: 3
    Dernier message: 29/06/2008, 23h07
  2. Héritage, classe virtuelle
    Par Anium dans le forum C++
    Réponses: 3
    Dernier message: 21/05/2008, 10h18
  3. Héritage, classe de base
    Par Melem dans le forum Mise en page CSS
    Réponses: 4
    Dernier message: 25/02/2008, 16h45
  4. Héritage classe template->classe template
    Par zabibof dans le forum Langage
    Réponses: 5
    Dernier message: 11/08/2007, 12h05
  5. Réponses: 5
    Dernier message: 10/01/2007, 03h08

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