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 :

Comment déterminer le type d'un objet pendant l'exécution


Sujet :

C++

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Août 2002
    Messages
    225
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2002
    Messages : 225
    Points : 118
    Points
    118
    Par défaut Comment déterminer le type d'un objet pendant l'exécution
    Bonjour à toutes et à tous,

    Voici mon soucis : j'ai une hiérarchie de classes et j'utilise un pointeur sur la classe de base pour manipuler tous mes objets. Ma classe de base étant abstraite et ses fonctions virtuelles, mes classes dérivées se chargent de l'implémentation des fonctions .. bref, je voudrais savoir comment faire pour déterminer le type des objets à partir du pointeur sur la classe de base qui me sert à manipuler mes objets.

    Je sais, ce n'est pas très clair alors je vais ajouter quelques lignes de codes.

    Si j'ai un hiérachie de classe comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    class CBase
    {
    }
     
    class CInherited : public CBase
    {
    }
    et que dans mon programme je fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    CInherited* pI = new CInherited;
    CBase* pB = pI;
    Comment je peux déterminer que pI est de type CInherited ?

    D'avance merci pour vos réponses.

  2. #2
    Expert éminent
    Avatar de Swoög
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    6 045
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 6 045
    Points : 8 339
    Points
    8 339
    Par défaut
    tu ne peux pas, il n'y a pas de fonction standard qui le permette (il y a bien le RTII, mais ça marche ni partout, ni à tous les coups)

    en général, si tu as besoin de repasser base => dérivé, c'est que tu as une erreur de conception quelque part...
    Rédacteur "éclectique" (XML, Cours PHP, Cours JavaScript, IRC, Web...)
    Les Règles du Forum - Mon Site Web sur DVP.com (Développement Web, PHP, (X)HTML/CSS, SQL, XML, IRC)
    je ne répondrai à aucune question technique via MP, MSN ou Skype : les Forums sont là pour ça !!! Merci de me demander avant de m'ajouter à vos contacts sinon je bloque !
    pensez à la balise [ code ] (bouton #) et au tag (en bas)

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Août 2002
    Messages
    225
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2002
    Messages : 225
    Points : 118
    Points
    118
    Par défaut
    Je n'ai pas besoin de passer de la classe de base vers la classe dérivée, simplement j'aurai aimé être en mesure de pouvoir déterminer la classe de l'objet que je manipule.

    Pour donner des informations sur ma motivation, je peux dire que j'ai implémenté un modèle de conception "état". J'ai un objet abstrait ETAT_IHM (ma classe de base) et pleins d'autres objets dérivés. J'ai un objet IHM qui possède une référence sur son état courant (via un pointeur sur la classe ETAT_IHM). Développant sous Qt j'aurais aimé tiré profit des signaux et notifier le changement d'état, en donnant le type de la classe référencée par le pointeur sur la classe ETAT_IHM.

    Je pense que je peux toujours implémenter un jeux de méthode get/setType mais franchement j'aime pas trop, ça me fait rajouter du code ... c'est pas par paresse mais ça gâche tout.

    Voila, peut être qu'il existe une solution à mon problème à laquelle je ne pense pas.

  4. #4
    Expert éminent
    Avatar de Swoög
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    6 045
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 6 045
    Points : 8 339
    Points
    8 339
    Par défaut
    OK ^^

    dans ce cas, penche toi sur le RTII... mais c'est sujet à caution, il y a un paragraphe dessus là dedans : http://www.developpez.biz/download/stl.pdf
    Rédacteur "éclectique" (XML, Cours PHP, Cours JavaScript, IRC, Web...)
    Les Règles du Forum - Mon Site Web sur DVP.com (Développement Web, PHP, (X)HTML/CSS, SQL, XML, IRC)
    je ne répondrai à aucune question technique via MP, MSN ou Skype : les Forums sont là pour ça !!! Merci de me demander avant de m'ajouter à vos contacts sinon je bloque !
    pensez à la balise [ code ] (bouton #) et au tag (en bas)

  5. #5
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    tu ne peux pas, il n'y a pas de fonction standard qui le permette (il y a bien le RTII, mais ça marche ni partout, ni à tous les coups)
    Si si.
    Le RTTI ça marche à tout les coups, normal c'est standard...

    Généralement on fait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if(CInherited* pI = dynamic_cast<CInherited*>(pB))
    Sinon il est aussi possible de faire des trucs à base typeid()
    Boost ftw

  6. #6
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    En effet, mais généralement rares sont les cas où le besoin de faire ceci ne vient pas d'une erreur de conception. Essaye de voir si tu peux faire autrement.
    Normalement du moment ou tu utilises le polymorphisme, c'est que tu dois faire "comme si" tous les objets étaient de mêmes types, en appelant la même fonction pour tous. Donc devoir traiter un type différemment, ce n'est pas "normal".
    Ce sujet a été traité deja dans le forum.

  7. #7
    Expert éminent
    Avatar de Swoög
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    6 045
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 6 045
    Points : 8 339
    Points
    8 339
    Par défaut
    Citation Envoyé par loufoque
    Si si.
    Le RTTI ça marche à tout les coups, normal c'est standard...
    cf paragraphe sur le RTII dans le pdf que j'ai indiqué

    Citation Envoyé par loufoque
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if(CInherited* pI = dynamic_cast<CInherited*>(pB))
    Je croyais que dynamic_cast levait un std::bad_cast en cas d'erreur de cast ton if risque de te surprendre ^^

    @Alp : là c'est dans le cadre du débuggage, c'est compréhensible...
    Rédacteur "éclectique" (XML, Cours PHP, Cours JavaScript, IRC, Web...)
    Les Règles du Forum - Mon Site Web sur DVP.com (Développement Web, PHP, (X)HTML/CSS, SQL, XML, IRC)
    je ne répondrai à aucune question technique via MP, MSN ou Skype : les Forums sont là pour ça !!! Merci de me demander avant de m'ajouter à vos contacts sinon je bloque !
    pensez à la balise [ code ] (bouton #) et au tag (en bas)

  8. #8
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    Swoog : en cas d'erreur de cast du dynamic_cast, il retourne un pointeur NULL(0 donc ...)

    Ensuite, dans le cadre du débuggage, pas besoin de performances, donc un simple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cout << typeid(monobjet).name << endl;
    suffit, si l'on a une console pour débuguer

  9. #9
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 379
    Points : 41 573
    Points
    41 573
    Par défaut
    dynamic_cast retourne NULL pour les pointeurs et lance une exception bad_cast pour les références.

    PS: Comment marche la RTTI pour les classes qui n'ont pas de fonctions virtuelles ? Je n'ai pas l'impression qu'elle agrandisse ses données...

    ??
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  10. #10
    Membre régulier
    Profil pro
    Inscrit en
    Août 2002
    Messages
    225
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2002
    Messages : 225
    Points : 118
    Points
    118
    Par défaut
    Waou, que de réponses.

    J'ai lu l'article sur le RTTI (problème de performance) avant de poster ma question initiale.

    J'ai maintenant d'autres questions :
    * Est ce que le RTTI est utilisable avec Qt ?
    * Comment activer/utiliser le RTTI ?


    Sinon j'ai toujours la possibilité d'ajouter une variable dans ma classe de base, variable qui pourra être initialisée par chacune de mes classes dérivées lors de la création des objets ... peut être que cette solution est moins pénalisante en terme de performances que le RTTI, en contrepartie mon architecture doit être modéifiée.

    Qu'en pensez vous ?

  11. #11
    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 : 49
    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
    Points : 16 213
    Points
    16 213
    Par défaut
    Je n'ai pas vu évoqués de problèmes de performance dans l'article en question... Qui par ailleurs est un peu daté et légèrement inexact.
    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.

  12. #12
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 279
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 279
    Points : 11 015
    Points
    11 015
    Par défaut
    Citation Envoyé par Yellowmat
    Pour donner des informations sur ma motivation, je peux dire que j'ai implémenté un modèle de conception "état". J'ai un objet abstrait ETAT_IHM (ma classe de base) et pleins d'autres objets dérivés. J'ai un objet IHM qui possède une référence sur son état courant (via un pointeur sur la classe ETAT_IHM). Développant sous Qt j'aurais aimé tiré profit des signaux et notifier le changement d'état, en donnant le type de la classe référencée par le pointeur sur la classe ETAT_IHM.
    Idéalement, à toi de voir si tes états n'ont pas ce petit quelque chose en commun qui sera exploité par l'observateur. Que cela soit une donnée ou une action à réaliser.
    Généralement, là où l'on fait un switch sur le type exact, on est en mesure de définir une fonction virtuelle dont les spécialisations implémentent les divers cas du switch.

    Il reste des cas où il faudrait limite un double switch (deux familles de classes sur lesquelles il faut choisir la fonction à exécuter). Litérature -> double dispatch, multi-methods. Le RTTI est alors à peu près la seule solution viable.

    Sinon, ton problème me rapelle de loin la mise en place du DP observateur-oservé. Je me souviens que j'avais réussi à faire un truc générique avec zéro down-casting. Le prix à payer fut un abus de templates et des héritages à l'"envers". Bref un truc compliqué, qui bien qu'esquivant le RTTI (et son coût, de plus en plus négligeable avec les dernières générations de compilos, IIRC), ne se justifie pas.

    La condition sinequanon pour utiliser le RTTI, en downcasting c'est que la classe doit disposer d'une vtable. Après il y avait des histoires d'options par défaut avec les vieux compilos.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  13. #13
    Membre expert
    Avatar de Eusebe
    Inscrit en
    Mars 2006
    Messages
    1 992
    Détails du profil
    Informations personnelles :
    Âge : 46

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 992
    Points : 3 344
    Points
    3 344
    Par défaut
    Je vais certainement dire une bétise, mais vous allez vite me dire pourquoi c'en est une ^^ (après tout, le forum sert à ça ).

    Pourquoi ne pas créer une fonction virtuelle dans la classe de base qui serait par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    virtual std::string getType() const {return "ClasseDeBase";}
    Puis dans chaque classe dérivée, l'implémenter en renvoyant le nom de la classe dérivée.

    Est-ce que ça pourrait fonctioner ?

  14. #14
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Citation Envoyé par Swoög
    cf paragraphe sur le RTII dans le pdf que j'ai indiqué


    Je croyais que dynamic_cast levait un std::bad_cast en cas d'erreur de cast ton if risque de te surprendre ^^

    @Alp : là c'est dans le cadre du débuggage, c'est compréhensible...
    Non, pas dans le cas des conversions de pointeur, c'est expliqué dans mon tuto sur les conversion non numériques de Boos - cf ma signature

    Citation Envoyé par Eusebe
    Je vais certainement dire une bétise, mais vous allez vite me dire pourquoi c'en est une ^^ (après tout, le forum sert à ça ).

    Pourquoi ne pas créer une fonction virtuelle dans la classe de base qui serait par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    virtual std::string getType() const {return "ClasseDeBase";}
    Puis dans chaque classe dérivée, l'implémenter en renvoyant le nom de la classe dérivée.

    Est-ce que ça pourrait fonctioner ?
    Ca me paraît être une bonne solution si on a pas besoin d'utiliser le type fils, mais juste le connaître.

  15. #15
    Alp
    Alp est déconnecté
    Expert éminent sénior

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Points : 11 860
    Points
    11 860
    Par défaut
    De toute manière, si l'on fait ça, le polymorphisme passe aux oubliettes.
    L'intêret du polymorphisme, c'est bien de, à partir de la classe de base, manipuler des objets étant tous des fils de cette classe de base, mais sans savoir qui est quoi.

  16. #16
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 279
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 279
    Points : 11 015
    Points
    11 015
    Par défaut
    Eusèbe. Ce que tu proposes, c'est de défiir à la main ce que le RTTI fait automatiquement en plus efficace.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  17. #17
    Membre expert
    Avatar de Eusebe
    Inscrit en
    Mars 2006
    Messages
    1 992
    Détails du profil
    Informations personnelles :
    Âge : 46

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 992
    Points : 3 344
    Points
    3 344
    Par défaut
    Citation Envoyé par Luc Hermitte
    Eusèbe. Ce que tu proposes, c'est de défiir à la main ce que le RTTI fait automatiquement en plus efficace.
    D'accord, merci.
    Mais j'avoue ne pas encore avoir bien compris ce que faisait la RTTI, et si elle le faisiat toujours

  18. #18
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    L'avantage de la solution à la main, c'est qu'on obtient un nom clair, parfois le RTII donne des noms à coucher dehors - parfois = tout le temps -.
    C'est bien le RTII qui est utilisé quand on utilise type_id ?

  19. #19
    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 : 49
    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
    Points : 16 213
    Points
    16 213
    Par défaut
    Il ne faut effectivement jamais utiliser le résultat de type_info::name pour autre chose que de l'affichae de debug. Il n'a pas été prévu pour ça, et par exemple une implémentation que retournerait la chaîne "Je suis un type, ça vous avance à quoi de le savoir" serait 100% conforme à la norme.

    A mon sens, l'outil le plus utile du RTTI, c'est surtout l'utilisation de dynamic_cast.

    Maintenant, quand son emploi est-il justifié ? Là où je l'utilise le plus souvent, c'est quand je dois m'insérer dans une hiérarchie d'héritage externe, que je ne peux pas modifier, et qui ne me donne pas les points d'entrée que je souhaite.
    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.

  20. #20
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    OK, on est d'accord donc

Discussions similaires

  1. [Free Pascal] Comment déterminer le type que rentre l'utilisateur
    Par Vitoo dans le forum Free Pascal
    Réponses: 6
    Dernier message: 26/11/2007, 13h35
  2. Réponses: 3
    Dernier message: 04/04/2007, 08h07
  3. Réponses: 6
    Dernier message: 27/06/2006, 23h26
  4. [POO] Comment connaître le type d'un objet
    Par zizou39 dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 01/03/2005, 09h46
  5. Comment detecter le type d'un objet?
    Par nickylarson dans le forum C++Builder
    Réponses: 3
    Dernier message: 24/06/2003, 15h23

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