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 :

typeid et ses drôles de types


Sujet :

C++

  1. #1
    Membre éclairé
    Inscrit en
    Septembre 2007
    Messages
    267
    Détails du profil
    Informations personnelles :
    Âge : 38

    Informations forums :
    Inscription : Septembre 2007
    Messages : 267
    Par défaut typeid et ses drôles de types
    Bonjour,
    Je suis les cours de C++ : http://cpp.developpez.com/cours/polyCpp/#LIV-I-2

    Je compile sur Code::Blocks ce code :

    .hpp
    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
    24
    25
    26
    27
    28
    #ifndef IV-I-2_HeaderFile
    #define IV-I-2_HeaderFile
     
    class Animal {
        virtual void uneFonction() { // il faut au moins une fonction virtuelle
         // (car il faut des classes polymorphes)
        }
    };
     
    class Mammifere : public Animal {
    };
     
    class Chien : public Mammifere {
     
    };
     
    class Caniche : public Chien {
     
    };
     
    class Chat : public Mammifere {
     
    };
     
    class Reverbere {
     
    };
    #endif
    .cpp

    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
    /*  Utilisation de typeid*/
    #include <iostream>
    #include <conio.h> // Permet d'utiliser getch()
    #include <typeinfo>
    #include "IV-I-2.hpp"
     
    using namespace std;
     
    int main() {
        Animal *ptr = new Caniche;
     
        cout << typeid(ptr).name() << '\n';
        cout << typeid(*ptr).name() << '\n';
        cout << "L'animal pointe par ptr "
       << (typeid(*ptr) == typeid(Chien) ? "est" : "n'est pas")
       << " un chien\n";
        cout << "L'animal pointe par ptr est un "
       << typeid(*ptr).name() << "\n";
        return getch();
    }
    et j'ai pour rendu ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    P6Animal
    7Caniche
    L'animal pointe par ptr n'est pas un chien
    L'animal pointe par ptr est un 7Caniche
    au lieu d'avoir cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Animal *
    Chien
    L'animal pointé par ptr n'est pas un chien
    L'animal pointé par ptr est un Caniche
    Please tell me why...

  2. #2
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 290
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 290
    Billets dans le blog
    2
    Par défaut
    Si on remplace les \n par des endl, la sortie est déjà plus proche de ce qui est attendu.
    Par contre, je ne comprend pas pourquoi.

  3. #3
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Les ' sont utilisé pour des caractères, '\n' est un entier.
    Les " sont utilisé pour les chaînes de caractères, "\n" est une chaîne de caractère.

    Je pense qu'en remplaçant les '\n' par des "\n" devrait donner un meilleurs résultat.

  4. #4
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    Salut

    Utilise std::endl au lieu de '\n' (ou "\n")
    Pour le problème avec typeid(ptr).name() qui retourne pas le nom correcte de la classe, c'est normal et non portable : un autre compilateur pourrait donner bien autre chose, ce qui est ton cas. C'est normalement utilisé pour débug et usage interne, pas pour faire de l'introspection

  5. #5
    Membre Expert
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Par défaut
    Probablement le compilo qui change un peu les noms (comme le mangling), Sous VS2012 j'obtient le résultat attendu.
    Sous gcc 4.8 j'obtient le même résultat que toi.

    Citation Envoyé par Neckara Voir le message
    Les ' sont utilisé pour des caractères, '\n' est un entier.
    Non c'est un char, c'est comme '\0' c'est un char correspondant au caractère de code ascii 0.
    typeid('\n').name() renvoi "char".

    edit:
    P6Animal
    -> P pointeur, 6 le 6eme type rencontré et enregistré, puis le nom de la classe

  6. #6
    Expert confirmé

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 033
    Billets dans le blog
    12
    Par défaut
    Citation Envoyé par Iradrille Voir le message
    edit:
    P6Animal
    -> P pointeur, 6 le 6eme type rencontré et enregistré, puis le nom de la classe
    P => pointeur
    6 => Nombre de lettres du nom du type

    Ca provient du name mangling de GCC.
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  7. #7
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Citation Envoyé par Iradrille Voir le message
    Non c'est un char, c'est comme '\0' c'est un char correspondant au caractère de code ascii 0.
    typeid('\n').name() renvoi "char".
    Je penses que tu confonds entier et "int".
    Un char est un entier tout comme un int.

    A ne pas confondre avec un caractère qui lui peut être codé sur un char ou plus (ex : utf-8, utf-16, utf-32, ...)

    D'après typeid, les caractères accentué comme 'é' seraient codé sur un int.

  8. #8
    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
    Citation Envoyé par Neckara Voir le message
    A ne pas confondre avec un caractère qui lui peut être codé sur un char ou plus (ex : utf-8, utf-16, utf-32, ...)
    Je crois que tu confonds character et wide character.

    Car un char est bien un character, et inversement.

  9. #9
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Citation Envoyé par oodini Voir le message
    Car un char est bien un character, et inversement.
    Non, c'est un raccourcit trop facile.
    On a associé aux valeurs prises par un char des codes ASCII.
    Et c'est ce code ASCII qui correspond à un caractère donné.

    Mais la taille d'un caractère est défini par l'encodage qu'on utilise.

    Un "caractère large" sert juste à désigner un caractère codé sur plus de 8 bits.

  10. #10
    Membre éclairé
    Avatar de gb_68
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2006
    Messages
    232
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Haut Rhin (Alsace)

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

    Informations forums :
    Inscription : Août 2006
    Messages : 232
    Par défaut
    Citation Envoyé par dragonjoker59 Voir le message
    P => pointeur
    6 => Nombre de lettres du nom du type

    Ca provient du name mangling de GCC.
    Tout à fait ; l'implémentation de type_info::name est laissée à la discrétion du couple compilateur/stl.
    Pour GCC il est possible de "démangler" avec abi::__cxa_demangle(évidemment non portable) : http://gcc.gnu.org/onlinedocs/libstd...emangling.html
    Citation Envoyé par gbdivers Voir le message
    Utilise std::endl au lieu de '\n' (ou "\n")
    Pourquoi forcer un flush à chaque ligne ? (endl = insertion de \n + flush, un à la fin devrait suffire)
    Citation Envoyé par FoX_*D i E* Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Animal *
    Chien
    L'animal pointé par ptr n'est pas un chien
    L'animal pointé par ptr est un Caniche
    On dirait plus une erreur du tutoriel . *ptr est bien de type Caniche, d'ailleurs les lignes 13 et 18 sont identiques typeid(*ptr).name().

  11. #11
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 290
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 290
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par gb_68 Voir le message
    Pourquoi forcer un flush à chaque ligne ?
    Parce que:
    1. Parce que si tu utilises un cout <<, c'est que la rapidité d'exécution n'est pas vraiment critique, ou du moins pas au point de gagner les quelques cycles du flush
    2. Parce que flusher après chaque output peut éviter des erreurs bêtes. Typiquement lors d'un debuggage: l'output n'est pas affiché donc le programme a planté avant (alors qu'en fait non, c'est juste que l'output n'a pas été "flushé")
    3. Parce que le code est plus facile à modifier.

    Après, il y a des arguments pour le \n, mais ce n'était pas la question

  12. #12
    Membre éclairé
    Inscrit en
    Septembre 2007
    Messages
    267
    Détails du profil
    Informations personnelles :
    Âge : 38

    Informations forums :
    Inscription : Septembre 2007
    Messages : 267
    Par défaut
    Bonsoir a tous,
    Je vous remercie pour vos réponses, ca m'a bien éclairé, et je suis décu du fait que ce code ne soit pas portable (enfin qu'il donne différents résultats selon le compilateur).

    Ceci dit, vous m'avez l'air divisés a propos de ces chiffres :
    c'est dûe au '\n' ou au nombre de lettres du nom du type (je pense que c'est le nombre de lettres, si c'est le cas, c'est quand même super zarbi provenant du compilateur, on se fou complétement du nombre de lettres du type rechérché ^^)

  13. #13
    Membre éclairé
    Avatar de gb_68
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2006
    Messages
    232
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Haut Rhin (Alsace)

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

    Informations forums :
    Inscription : Août 2006
    Messages : 232
    Par défaut
    Citation Envoyé par r0d Voir le message
    1. Parce que si tu utilises un cout <<, c'est que la rapidité d'exécution n'est pas vraiment critique, ou du moins pas au point de gagner les quelques cycles du flush
    2. Parce que flusher après chaque output peut éviter des erreurs bêtes. Typiquement lors d'un debuggage: l'output n'est pas affiché donc le programme a planté avant (alors qu'en fait non, c'est juste que l'output n'a pas été "flushé")
    Je suis d'accord ; remplacer des endl par des '\n' dans un cas comme celui-ci serait clairement de l'optimisation prématurée (à supposer même que l'on puisse gagner quelque chose sur ce genre de code).
    Mais inversement, ce qui m'étonnait ici, c'était le nombre de réponses sur remplacer unilatéralement tous les '\n' par des endl alors que cela ne changeait pas le problème et les différences entre ces deux approches n'étaient pas plus explicitées (certes négligeables ici).

    Citation Envoyé par FoX_*D i E* Voir le message
    c'est dûe au '\n' ou au nombre de lettres du nom du type (je pense que c'est le nombre de lettres, si c'est le cas, c'est quand même super zarbi provenant du compilateur, on se fou complétement du nombre de lettres du type rechérché ^^)
    Comme l'avait dit dragonjoker59, les chiffres proviennent bien du "mangling" GCC (regard le lien que j'avais donné : 3barI5emptyLi17EE pour bar<empty, 17> ).

    Après c'est un choix d'implémentation que de fournir des noms décorés ou autre chose pour type_info::name.
    A titre d'exemple ce même code sous VS C++ 2010 me donne
    class Animal *
    class Caniche
    L'animal pointe par ptr n'est pas un chien
    L'animal pointe par ptr est un class Caniche

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Au passage, je trouve ce test douteux:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        cout << "L'animal pointe par ptr "
       << (typeid(*ptr) == typeid(Chien) ? "est" : "n'est pas")
       << " un chien\n";
    Il fait une comparaison stricte sur le type, pour dire "est" ou "n'est pas", mais la notion d'héritage public est traditionnellement définie comme une relation "est-un".

    Donc, il faudrait soit changer le message en " EXACTEMENT un chien", soit remplacer la comparaison de typeid par un test de cast dynamique:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        cout << "L'animal pointe par ptr "
       << (dynamic_cast<Chien*>(ptr) != NULL ? "est" : "n'est pas")
       << " un chien\n";
    (Note: Remplaçer NULL par nullptr si le compilo est assez récent pour le supporter).
    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.

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 20/05/2009, 15h16
  2. Coloration de ses types
    Par Bakura dans le forum Visual C++
    Réponses: 0
    Dernier message: 05/11/2008, 21h54
  3. creer ses propres type de données
    Par charlie_p07 dans le forum PostgreSQL
    Réponses: 4
    Dernier message: 14/04/2008, 17h22
  4. Réponses: 1
    Dernier message: 05/08/2007, 14h46

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