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 :

Acceder à une variable d'une classe dérivée Lorsque l'on a un pointeur du type de la classe de base


Sujet :

C++

  1. #1
    Invité
    Invité(e)
    Par défaut Acceder à une variable d'une classe dérivée Lorsque l'on a un pointeur du type de la classe de base
    Bonjour à tous !

    Je rencontre actuellement un problème avec l'héritage dans mon projet que j'ai résumé dans le schéma suivant :

    Nom : 396140.png
Affichages : 76
Taille : 11,2 Ko

    En effet, je ne parviens pas à implémenter la fonction isSwordsDrawn() car je ne peux accéder à mSwordsDrawn...

    Que puis-je faire ?

    Merci d'avance !
    Dernière modification par Domi2 ; 13/08/2012 à 09h41. Motif: image en pièce jointe !

  2. #2
    Invité
    Invité(e)
    Par défaut
    si tu manipules un Player*, tu ne peux pas appeler isSwordDrawn car c'est pas une méthode de Player.

    Tu peux faire un dynamic_cast pour convertir ton Player en SinbadCharacter (qui pour le coup présente bien la méthode isSwordDrawn)

    Tu peux sinon écrire simplement SinbadCharacter* mplayer=new SinbadCharacter

  3. #3
    Invité
    Invité(e)
    Par défaut
    Ok merci !
    Je suis en train de réfléchir à ce que tu me dis et je me demande si il est possible de connaitre exactement le type de la classe de mon pointeur ?

    Évidemment à part utiliser une variable dans la classe de base que je modifierais dans le constructeur de chaque classe dérivée ?

    Merci encore !

    Edit: résolu.
    Dernière modification par Flob90 ; 13/08/2012 à 00h28. Motif: Pas de lien externe

  4. #4
    screetch
    Invité(e)
    Par défaut
    dans ce cas la tu n'as pas besoin d'heritage, l'heritage est fait pour traiter de maniere unifiee des objets de types differents.
    Soit:
    - tu sais que ton player est un SinbadCharacter et il n'y a pas besoin de le traityer comme un Player generique
    - tu ne sais pas que c'est un SinbadCharacter car ca pourrait etre quelque chose d'autre et dans ce cas tu ne dois pas acceder a des methodes specifiques de SinbadCharacter.

    Revois ton design et repond a cette question: le PlayerManager, sait-il que c'est un SinbadCharacter?

  5. #5
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Bonjour,

    Un dynamic_cast est signe d'un problème de conception ( en général, ça aboutit à violer le open/close principle).

    Soit c'est la mauvaise abstraction qui est manipulée (ce qu'indique Screetch) : la classe utilisatrice PlayerMgr doit elle manipuler par l'interface de base Player ou par l'interface dérivée Sinbad ?

    Soit l'abstraction manipulée est incomplète : PlayerMgr n'a-t-il pas en réalité besoin d'un IsWeaponDrawn sur une interface Player ( au besoin mise en œuvre par Sinbad comme un isSwordsDrawn) ?

    Soit la responsabilité est mal distribuée dans le contrat : ce qu'essaie de faire PlayerMgr avec isSwordsDrawn relèverait mieux d'une autre fonction plus complète du Player. Typiquement if(!player->IsSwordsDrawn()){player.DrawSwords();}) à remplacer par un player.DrawSwords(); direct, à charge de DrawSwords de vérifier ce qui doit être fait en fonction de son état interne.

    ou encore, carrément un design inapproprié : peut être un visiteur conviendrait-il mieux ?


    Quelques liens :

    F.A.Q : Pourquoi mettre en œuvre un héritage ?
    F.A.Q : Qu'est-ce que le LSP ?

    Open/Close principle chez Emmanuel

    Et pour le plaisir, puisque dans PlayerMgr, il est fort à parier que Mgr est une contraction pour Manager et non pour Monseigneur comme il se doit, à lire aussi : De la gestion des gestionnaires.

    Enfin, juste une remarque sur le nom SinbadCharacter. Chez moi, Sinbad fait écho à un personnage, pas à un archétype (disons dans ce qui ressemble à un jeu. A moins que ton jeu use d'antonomase mais cela me semblerait maladroit en terme de maintenance). Donc SinbadCharacter serait une instance de Player et non une classe dérivée. Une classe dérivée serait Sailor par exemple.

  6. #6
    Invité
    Invité(e)
    Par défaut
    Un dynamic_cast est signe d'un problème de conception
    Décidément

    Sinon, c'est pas parce qu'on peut se passer du dynamic_cast qu'il ne faut pas le connaitre... ne serait-ce que pour se questionner sur son utilisation.

  7. #7
    screetch
    Invité(e)
    Par défaut
    en l'occurrence c'est ce que l'auteur a fait et on conseilel de ne pas l'utiliser, surtout dans ce cas
    j'ai une utilisation valable de dynamic_cast dans mon projet; c'est pour verifier qu'un cast est valable.

    il arrive parfois que l'on perde l'information de type mais que l'on sache exactement de quel type il s'agit; les exemples ou ca arrive pevent etre assez nombreux, le cas principal c'est en gros une hierarchie de classe A->A'->A'' et B->B'->B'' ou A connait B.
    Et souvent on a la meme association a tous les niveaux; A' connait B' et A'' connait B'', car elles travaillent ensemble.

    Pense par exemple a une classe Renderer dont derivent OpenGLRenderer et DirectX renderer.
    Et une classe SHader dont derivent OpenGLShader et DIrectXShader.
    Il est bien evident que DirectXRenderer traitent des shaders qui sont de type DirectXShader, pas des OpenGLShader.

    Pourtant selon l'architecture, il se peut que l'association Renderer-Shader soit faite dans les classes de base, pas dans les classes les plus precises.
    Mais comme on sait que le Renderer est un DirectXRenderer, on a pas besoin d'un dynamic_cast; un static_cast suffit.

    La ou c'est interessant, c'est que l'on peut utiliser un dynamic_cast pour verifier que l'objet est bien de la bonne classe; on peut faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    template< typename U, typename T >
    U* checked_cast(T* t)
    {
      assert(dynamic_cast<U*>(t) != 0 && "t n'est pas un U!");
      return static_cast<U*>(t);
    }


    on a donc une verification au runtime de tous les cast ou on avait perdu le type statique.



    C'est le seul cas que je connaisse de dynamic_cast, le reste indique un souci de conception.

  8. #8
    Invité
    Invité(e)
    Par défaut
    on a pas besoin d'un dynamic_cast; un static_cast suffit
    Je suis assez frileux avec les cast. Mais effectivement si tu remplaces par un static, je vois egalement peu d'exemple ou le dynamic est indispensable. Mais je suis certain que certains en ont

    De maniere plus generale on a tendance a perdre le type statique lorsqu'on a une classe qui manipule des abstractions du genre
    Container contient des B, et des C...sous forme de A (classe mere)
    Un accesseur du container retourne soit des B ou des C.

    Si l'appelant demande un B particulier, le container doit retourner la dite instance de B sous forme de B.

    Auquel cas, un bon vieux cast dans le container, invisible pour l'appelant a lieu.

  9. #9
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Bonjour,

    Citation Envoyé par galerien69 Voir le message
    Sinon, c'est pas parce qu'on peut se passer du dynamic_cast qu'il ne faut pas le connaitre... ne serait-ce que pour se questionner sur son utilisation.
    Effectivement. On peut toujours donner un marteau quand on a besoin de visser. Après tout, en tapant bien fort, ça finira par rentrer. (mais question maintenance, évolution...).
    Ou expliquer en quoi un tournevis sera plus adéquat.

    Citation Envoyé par screetch Voir le message
    il arrive parfois que l'on perde l'information de type mais que l'on sache exactement de quel type il s'agit; les exemples ou ca arrive pevent etre assez nombreux, le cas principal c'est en gros une hierarchie de classe A->A'->A'' et B->B'->B'' ou A connait B.
    Et souvent on a la meme association a tous les niveaux; A' connait B' et A'' connait B'', car elles travaillent ensemble.
    en attendant les mutliméthodes. cf V comme Visiteur pour un exemple.

  10. #10
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    576
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2011
    Messages : 576
    Points : 1 528
    Points
    1 528
    Par défaut
    On peut toujours donner un marteau quand on a besoin de visser. Après tout, en tapant bien fort, ça finira par rentrer.
    Par chez moi on appel ça "visser à la parisienne". C'est assez pratique pour "visser" des plaques d'aglo. Ca permet d'orienter les fibres du bois vers l'intérieur et empêcher la vis de ressortir .

    Sinon les seuls cas où je trouve le dynamic_cast utile est lorsqu'on a un algo qui marche avec tous les objet de type A, mais où on a une meilleur version spécifique pour des objets de type B dérivant de A. Mais cela ne reste que de l'optimisation.
    La perfection est atteinte, non pas lorsqu’il n’y a plus rien à ajouter, mais lorsqu’il n’y a plus rien à retirer. - Antoine de Saint-Exupéry

  11. #11
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Mais, dans ce cas, ne peut-on pas rendre l'algo template et le spécialiser pour B?
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  12. #12
    Membre expérimenté
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    576
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2011
    Messages : 576
    Points : 1 528
    Points
    1 528
    Par défaut
    Ca serait l'idéal, mais si tu perd le type de B en cour de route ou que l'interface de ton algo prend un A cela risque de demander beaucoup de refactoring.
    La perfection est atteinte, non pas lorsqu’il n’y a plus rien à ajouter, mais lorsqu’il n’y a plus rien à retirer. - Antoine de Saint-Exupéry

  13. #13
    Invité
    Invité(e)
    Par défaut
    Effectivement. On peut toujours donner un marteau quand on a besoin de visser. Après tout, en tapant bien fort, ça finira par rentrer. (mais question maintenance, évolution...).
    Ou expliquer en quoi un tournevis sera plus adéquat.
    que d'agressivite.

    je suis pas sur que la metaphore soit bien adaptee.
    eventuellement colmater une breche par du scotch plutot que colmater plus mettre une couche de peinture dessus ok.

    Mais non, un cast c'est pas overkill. Et j'aurais plutot tendance a dire le contraire.

    Quand au principal probleme, c'est a ton honneur de vouloir tirer les vers du nez a durium.

    Est-ce la bonne methode?

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

Discussions similaires

  1. récupérer une variable d'une fonction dans une classe
    Par free_dom dans le forum Général Python
    Réponses: 20
    Dernier message: 08/07/2009, 12h35
  2. Garder une référence vers une variable d'une autre classe
    Par choupeo dans le forum Windows Forms
    Réponses: 5
    Dernier message: 08/12/2007, 18h30
  3. Appliquer une methode a une variable d une classe ?
    Par Slumpy dans le forum VB.NET
    Réponses: 18
    Dernier message: 07/06/2007, 17h17
  4. Réponses: 6
    Dernier message: 20/04/2007, 15h24
  5. Désigner une variable avec une variable?
    Par littleman dans le forum Paradox
    Réponses: 4
    Dernier message: 12/08/2002, 11h21

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