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 :

Récupérer le nom d'une classe ainsi que la méthode dans laquelle on se trouve


Sujet :

C++

  1. #1
    Membre averti Avatar de nekcorp
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2006
    Messages
    592
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2006
    Messages : 592
    Points : 383
    Points
    383
    Par défaut Récupérer le nom d'une classe ainsi que la méthode dans laquelle on se trouve
    Bonjour,

    Je souhaite savoir s'il est possible lorsque l'on se trouve dans une classe de récupérer le nom de cette classe ainsi que la méthode dans laquelle on se trouve.

    Mon but est de de récupérer ces deux informations pour afficher un message d'erreur et que je sache rapidement où j'ai un soucis.

    Actuellement je rentre en dur dans ma fonction qui renvoie le message, le nom de la classe et de la méthode ou je me trouve. Ce que je souhaite c'est savoir s'il existe nativement quelque chose qui permet de récupérer ces informations.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    class myClass
    {
         public:
             void afficher();
    };
     
    void myClass::afficher()
    {
         // ici je souhaite récupérer le nom myClass et la méthode afficher
        errorMessage(className, methodName, msg);
     
        //Actuellement je rentre en dur le nom de la class et le nom de la method
        errorMessage("myClass", "afficher", msg);
    }
    Merci d'avance pour vos réponses.

  2. #2
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 565
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 565
    Points : 7 648
    Points
    7 648
    Par défaut
    Bonjour,

    Tu peux retrouver le nom de la fonction courante en utilisant __function__.
    Quand à la classe courante, tu peux l'obtenir par son type_info en faisant typeid(*this).name().

  3. #3
    Membre averti Avatar de nekcorp
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2006
    Messages
    592
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2006
    Messages : 592
    Points : 383
    Points
    383
    Par défaut
    Merci

    par contre tu serais me dire pourquoi j'ai un chiffre 7 devant le nom de ma classe ?

    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
    #include <iostream>
    #include <typeinfo>
     
    class myClass
    {
        public:
            void afficher();
    };
     
     
    void myClass::afficher()
    {
        std::cout << "Call afficher !" << std::endl;
     
        std::cout << typeid(*this).name() << std::endl;
     
        std::cout << __FUNCTION__ << std::endl;
    }
     
    int main()
    {
        myClass theClass;
        theClass.afficher();
     
        return 0;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Call afficher !
    7myClass
    afficher
    J'ai l'impression que c'est la taille du nom de la classe. J'ai modifié le nom de la classe et ça à l'air de se confirmer, le 7 est passé à 10 et le nom de ma classe fait 10 caractères

  4. #4
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    Pourquoi n'utiliserais tu pas, tout simplement, les assertions

    Il s'agit là d'une des rares techniques issues du C que vous me verrez plébisciter à chaque fois que j'en aurai l'occasion, il s'agit donc d'en profiter

    L'idée générale est d'inclure le fichier <cassert> et d'utiliser la macro assert(condition_devant_etre_vraie) pour repérer les éventuelles préconditions qui ne seraient pas remplies.

    Pour info, une précondition est -- en programmation "par contrat" -- une condition qui doit impérativement être (vérifiée et) validée au grand plus tard au moment où la fonction commence à s'exécuter. Ce sont, pour faire "aussi simple que possible", entre autres, toutes les conditions que les paramètres transmis à la fonction devront respecter pour que la fonction soit en mesure de fournir un résultat attendu et cohérent

    Toujours dans le soucis de simplifier les choses, on peut dire qu'une précondition mettra en avant les problèmes liés à la programmation: c'est parce que l'utilisateur d'une fonction n'a -- a priori -- pas fait toutes les vérifications nécessaires sur les données qu'ils s'apprête à transmettre à la fonction que le problème survient, et c'est l'une des causes principales de bugs.

    L'utilisation générale des assertions pourrait prendre une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void laFoncitonQuiNousInteresse(Type param){
        assert(laCondition_requise_pour_param);
        /* la suite du code */
    }
    Accessoirement, pour rendre le message affiché en cas de problème, on peut améliorer un peu les choses en utilisant une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void laFoncitonQuiNousInteresse(Type param){
        assert(laCondition_requise_pour_param && "un message explicite désignant le problème");
        /* la suite du code */
    }
    Ainsi, un code qui pourrait être aussi simple que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #include <cassert>
    #include <iostream>
    #include <cmath>
    float squareRoot( float value){
        /* Pour rappel: on ne peut calculer la racine carrée que
         * pour les valeurs strictement positive
         */
        assert(value> 0.f && "invalid value dectected");
        return std::sqrt(value);
    }
    int main(){
            std::cout<<"this will work :"<<squareRoot(3.1415926)<<"\n";
            std::cout<<"and assertion wil fail here"<<squareRoot(.0f)<<"\n";
    }
    nous présentera à l'exécution un résultat proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    a.exe
    this will work :1.77245
    and assertion wil fail hereAssertion failed: value> 0.f && "null value dectected", file main.cpp, line 5
    (==>voici la preuve <==)

    Il y a de nombreux avantages à travailler de cette manière, parmi lesquels on peut citer:

    Le fait que le programme plantera systématiquement (en mode debug) si la condition imposée par l'assertion n'est pas respectée. Il n'est en effet jamais bon de laisser tourner un programme si une précondtion n'est pas remplie, car autrement, on se retrouve dans une situation dans laquelle on ne peut plus faire confiance au résultat que l'on obtient, lorsque "le hasard" veut que l'on obtienne malgré tout un résultat pouvant "passer pour être correct"

    Le message affiché dans la console va directement t'indiquer non seulement quelle condition n'est pas remplie, mais également le fichier et -- cerise sur le gâteau -- la ligne à laquelle cette condition se trouve dans ton code.

    L'utilisateur de ta fonction (comprend: celui qui décide de faire appel à la fonction en lui donnant une valeur qu'il n'a pas "suffisamment vérifiée") n'aura pas d'autre choix que de corriger le problème, car il ne pourra pas aller plus loin

    Tu peux, au besoin (et si tu n'applique pas TDD) placer un breakpoint sur ton assertion, de manière à retrouver plus facilement l'origine de la donnée invalide.

    La macro peut être désactivée en définissant le symbole NDEBUG une fois que tu es sur que tous les appels à la fonction garantissent que les valeurs correctes sont transmises. Lorsque ton code passe "en production", elle sera simplement transformée en "no op": il n'y aura aucune instruction de test "résiduelle" dans le code binaire exécutable qui sera envoyé en production

    Cela fonctionne pour tous les types de fonctions: que ce soit des fonctions libres, des fonctions membres d'une classe, des fonctions virtuelles, ou même des fonctions template

    Accessoirement, depuis C++11, tu peux également utiliser static_assert, qui fonctionne sensiblement sur le même principe, mais qui vérifie les conditions imposées aux constantes de compilation au moment de la compilation.

    Après, bien sur, il y a tous les cas où l'information "invalide" que l'on manipule vient "d'ailleurs" (comprends: d'un serveur qui ne répond pas, d'un utilisateur du programme qui introduit une information incorrecte, ou que sais-je)

    Ce sont des cas que l'on ne peut pas se permettre d'ignorer, tout en espérant qu'ils ne se présenteront jamais (et en sachant qu'il finiront forcément par arriver, du fait de la loi de Murphy ' )

    Dans ces cas là, l'idéal est d'avoir recours au système d'exception: si une condition "extérieure" n'est pas remplie, le mieux est encore de lancer une exception et, dans l'idéal, de faire en sorte que cette exception soit spécifique au problème rencontré.

    Cette manière de travailler nous permettra de "remonter la pile d'appels" jusqu'au moment où nous serons effectivement en mesure de traiter le problème (à l'aide d'un bloc try ... catch) et d'y apporter (potentiellement) une solution.

    Quoi qu'il en soit, il faut te dire que cela ne sert à rien d'afficher un message d'erreur si tu n'est pas en mesure de résoudre le problème indiqué. Il peut, bien sur, être intéressant d'inscrire le problème dans un log, mais, s'il n'est pas résolu, cela ne te permettra pas d'obtenir un résultat cohérent et -- surtout -- fiable

    Les assertions et les exceptions par contre te permettent de permettre de mettre en place une procédure susceptible de t'aider à apporter une solution.
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #5
    Membre chevronné Avatar de Astraya
    Homme Profil pro
    Consommateur de café
    Inscrit en
    Mai 2007
    Messages
    1 043
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Consommateur de café
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mai 2007
    Messages : 1 043
    Points : 2 234
    Points
    2 234
    Par défaut
    Citation Envoyé par nekcorp Voir le message
    Merci

    par contre tu serais me dire pourquoi j'ai un chiffre 7 devant le nom de ma classe ?
    Typeid n'offre aucune garantie quand a la valeur retourné, elle dépends entièrement de ce que fait le compilateur avec les noms de symbole.
    Pendant la compilation c'est noms sont "manglé" et doivent être "démanglé" ! Le mangling est le résultat d'une étape de compilation nécessaire au compilateur pour identifier ta fonction/classe de façon unique en lui ajoutant des informations.
    Pour démanglé, tu as le header 'cxxabi.h' de mémoire et pour windows c'est avec l'API Win32.
    Homer J. Simpson


  6. #6
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1

  7. #7
    Membre averti Avatar de nekcorp
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2006
    Messages
    592
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2006
    Messages : 592
    Points : 383
    Points
    383
    Par défaut
    Merci pour vos réponses, je vais réussir à me débrouiller maintenant.

  8. #8
    Membre actif Avatar de Suryavarman
    Homme Profil pro
    Développeur 3D
    Inscrit en
    Mai 2006
    Messages
    233
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur 3D
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Mai 2006
    Messages : 233
    Points : 245
    Points
    245
    Par défaut
    Si tu veux j'ai eu aussi ce soucis. Voici mon bout de code:
    https://framagit.org/Suryavarman/ma/...de/API/Error.h

    J'en suis asse content.

    La partie importante qui t'intéresses doit être ça:
    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
     
    #if defined(__cpp_lib_source_location)
        #include <source_location>
    #endif
     
    #if defined(__cpp_lib_source_location)
        #define M_FUNCTION_NAME \
            std::source_location::current().function_name()
    #elif MA_COMPILER == MA_COMPILER_GNUC
        #define M_FUNCTION_NAME \
            __PRETTY_FUNCTION__
    #elif MA_COMPILER == MA_COMPILER_CLANG
        #define M_FUNCTION_NAME \
            __PRETTY_FUNCTION__
    #elif MA_COMPILER == MA_COMPILER_MSVC
        #define M_FUNCTION_NAME \
            __FUNCSIG__
    #else
        #error("La définition automatique du nom de la fonction courante n'est pas gérée pour le compilateur courant.")
    #endif
    "Quand le monde est dangereux, l'humilité est un facteur de longévité." ( Baxter "Evolution" )

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

Discussions similaires

  1. Récupérer le nom d'une classe et d'une méthode
    Par hanubis37 dans le forum Langages
    Réponses: 2
    Dernier message: 21/11/2014, 11h50
  2. récupérer le nom d'une classe javascript
    Par dark poulpo dans le forum Général JavaScript
    Réponses: 18
    Dernier message: 09/08/2012, 12h34
  3. Réponses: 22
    Dernier message: 19/01/2011, 10h00
  4. [Free Pascal] Récupérer un caractère d'une WideString ainsi que sa longueur
    Par bubulemaster dans le forum Free Pascal
    Réponses: 0
    Dernier message: 29/06/2009, 09h21
  5. Réponses: 4
    Dernier message: 23/04/2006, 10h36

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