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

Langage C++ Discussion :

utilisation de typeid


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre très actif

    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 685
    Par défaut utilisation de typeid
    Bonjour,

    j'ai une méthode qui n'est pas redéfinit dans ses classes filles car identique dans tous les cas jusqu'à maintenant.

    J'aimerais néanmoins, sans modifier ce détail car le code est trop important pour être autant modifier pour une simple correction(et puis je ne peux pas trop modifier le code de toute façon), pouvoir tester dans la classe mère, si le type de l'objet courant est d'un certain type :

    if (typeid(this) != typeid(MaClasseFille*).

    if (typeid(this).name != "MaClasseFille*")
    j'ai testé ceci, mais dans le premier cas, le compilo me sort un "undeclared identifier" et dans le second un problème de conversion :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    error C2040: '!=' : 'const char *(__thiscall type_info::* )(void) const' differs in levels of indirection from 'const char [16]'
    error C2446: '!=' : no conversion from 'const char *' to 'const char *(__thiscall type_info::* )(void) const'
            There is no context in which this conversion is possible
    error C2475: 'type_info::name' : forming a pointer-to-member requires explicit use of the address-of operator ('&') and a qualified name
    error C2475: 'type_info::name' : forming a pointer-to-member requires explicit use of the address-of operator ('&') and a qualified name
    Auriez-vous une idée de comment je peux m'en sortir sans trop de casse ?

    Edit :
    pour la première version, je comprend bien que ce soit délicat pour une classe mère d'identifier "ses filles", mais je le mets au cas où vous auriez des infos à ce sujet.

    J'ai vu que typeid était plus performant qu'un dynamic_cast<type> ou qu'un std::typeinfo, c'est vrai ? (et je savais pas qu'un dynamic_cast servait à cela).



    EDIT2 : problème réglé, j'ai appelé la méthode name(), par contre il me retourne toujours le type de la classe mère (je sais en l'état c'est normal, je suis bête ).

    Du coup ma question se résume à : comment je fais pour savoir de quel classe fille est issue l'appel à ma méthode ?

  2. #2
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Dans le premier cas, c'est normal : la classe mère ignore tout des classes qui en héritent

    Il faudrait, pour que typeid(this) == typeid(MaClasseFille*) que le compilateur connaisse au minimum le type de MaClasseFille, ce qui serait une énorme erreur de conception

    Et, de manière générale, je te déconseille fortement de faire appel à un type dérivé dans la classe de base

    J'aurais déjà tendance à te conseiller de vérifier si la fonction en question est virtuelle ou non, car, si elle ne l'est pas, c'est que le concepteur de la classe de base ne considérait pas utile que cette fonction soit redéfinie (et il n'y a normalement pas à le faire )

    Si la fonction est virtuelle et que tu souhaites récupérer le code correspondant à l'exécution de la classe de base, il t'est toujours possible d'invoquer explicitement ce comportement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    void DerivedClass::doSomething() /* const */
    {
        /* ce qui doit etre effectué avant l'appel explicite du code de la classe
         * mère
         *
         */
        BaseClass::doSomething();
     
        /* ce qui doit etre effectué après l'appel explicite du code de la classe
         * mère
         *
         */
    }
    Si cela ne t'est pas possible, parce que, par exemple, la partie spécifique à effectuer devrait se placer "au bon milieu" de la version propre à la classe mère, c'est très certainement que cette fonction en fait trop et mériterait amplement d'être revue de manière à factoriser une partie de son code
    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

  3. #3
    Membre très actif

    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 685
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Salut,

    Dans le premier cas, c'est normal : la classe mère ignore tout des classes qui en héritent
    Oui, c'est ce que je me suis dépêché de dire dans mon premier edit

    Citation Envoyé par koala01 Voir le message
    Et, de manière générale, je te déconseille fortement de faire appel à un type dérivé dans la classe de base
    ça ne me plait pas trop non plus...

    Citation Envoyé par koala01 Voir le message
    J'aurais déjà tendance à te conseiller de vérifier si la fonction en question est virtuelle ou non, car, si elle ne l'est pas, c'est que le concepteur de la classe de base ne considérait pas utile que cette fonction soit redéfinie (et il n'y a normalement pas à le faire )
    non virtuelle... et le concepteur avait raison de le considérer à l'époque, mais depuis, des classes filles ont vu le jour, et elles ont toutes le travail de la méthode non-virtuelle à accomplir, alors qu'il faudrait qu'une seule seulement s'en occupe...

    Je peux créer une méthode virtuelle qui encapsule la partie du traitement concerné, et que je redéfini juste dans ma nouvelle classe fille a priori .... pas d'objections ?


    En tout cas merci encore à vous (encore vous ) d'avoir pris le temps de me répondre

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par Kaamui Voir le message
    Oui, c'est ce que je me suis dépêché de dire dans mon premier edit



    ça ne me plait pas trop non plus...



    non virtuelle... et le concepteur avait raison de le considérer à l'époque, mais depuis, des classes filles ont vu le jour, et elles ont toutes le travail de la méthode non-virtuelle à accomplir, alors qu'il faudrait qu'une seule seulement s'en occupe...

    Je peux créer une méthode virtuelle qui encapsule la partie du traitement concerné, et que je redéfini juste dans ma nouvelle classe fille a priori .... pas d'objections ?


    En tout cas merci encore à vous (encore vous ) d'avoir pris le temps de me répondre
    Oui, mais veilles à lui donner un autre nom (ou une liste d'arguments différente), à cette fonction virtuelle qui encapsule l'ancienne fonction

    Autrement, tu auras des problèmes car le compilateur ne saura pas, si tu ne disposes que d'un pointeur sur la classe de base, qu'il doit aller voir si la fonction est virtuelle dans les classes dérivées
    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 Expert
    Avatar de ericd69
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    1 919
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 1 919
    Billets dans le blog
    1
    Par défaut
    salut,

    typeid est une spécificité du rtti, as tu bien utilisé les bonnes options (dépendant du compilateur) pour activer ces fonctionnalités?

    tu confondrais pas un peu c++ avec c#, javascript ou php par exemple? où as tu vu en c++ une surcharge des opérateurs de comparaison pour les chaine de caractère hors de l'utilisation de la classe string?

    du coup forcément lui voit que tu lui demandes de comparer des choses avec des types incompatibles donc il te dit les différentes choses impossibles qu'il a essayé de faire...

    si tu veux comparer des chaine y des fonction pour ça...


    koala le polymorphisme, ça a pas pour but de mettre un pointeur sur la classe de base et si celui-ci pointe sur une classe dérivé faire appel aux méthodes dérivées?

    le seul problème est donc de bien concevoir son modèle POO...


  6. #6
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par ericd69 Voir le message

    koala le polymorphisme, ça a pas pour but de mettre un pointeur sur la classe de base et si celui-ci pointe sur une classe dérivé faire appel aux méthodes dérivées?
    Si, mais, vu que la fonction n'est pas déclarée virtuelle dans la classe de base, le fait de la rendre virtuelle dans la classe dérivée aura pour conséquence de simplement cacher la fonction de la classe de base dans la classe dérivée, sans assurer pour autant le polymorphisme :

    Si tu travailles avec un pointeur (ou une référence) sur le type de base, c'est la version (non virtuelle!!) de la fonction qui sera appelée quoi qu'il arrive, meme si le pointeur pointe en réalité sur (ou la référence fait en réalité référence à) un pointeur du type dérivé

    Par contre, ca marche dans l'autre sense : si une fonction est déclarée virtuelle dans la classe de base, elle est implicitement déclarée virtuelle dans la classe dérivée même si l'utilisateur ne précise plus qu'elle l'est

    Un exemple pour comprendre
    Ce qui ne marche pas
    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
     
    class BadBase
    {
        public:
            void doSomething(); // fonction non virtuelle
    };
    class BadDerieved : public BadBase
    {
        public;
            virtual void doSomething(); // cache la déclaration (non virtutelle)
                                            // de BadBase::doSomething(); 
    };
    int main()
    {
         BadDerived d;
         d.doSomething(); // OK : appel de BadDerived::doSomething()
         BadBase * ptr = new BadDerived;
         ptr->doSomething(); // KO : appel de BadBase::doSomething()
    }
    ce qui marche
    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
     
    class Base
    {
        public:
            virtual void doSomething(); // fonction explicitement virtuelle
    };
    class Derived : public Base
    {
        public:
            void doSomething(); // fonction implicitement virtuelle car elle est
                        // déclarée virtuelle dans la classe de base
    };
    int main()
    {
        Derived d;
        d.doSomething(); // pas de polymorphisme en jeu ici :D
        Base * ptr = new Derived;
        ptr->doSomething(); // OK : Base::doSomething() est virtuelle, 
                          // le polymorphisme fonctionne
    }
    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

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

Discussions similaires

  1. utiliser les tag [MFC] [Win32] [.NET] [C++/CLI]
    Par hiko-seijuro dans le forum Visual C++
    Réponses: 8
    Dernier message: 08/06/2005, 15h57
  2. Réponses: 4
    Dernier message: 05/06/2002, 14h35
  3. utilisation du meta type ANY
    Par Anonymous dans le forum CORBA
    Réponses: 1
    Dernier message: 15/04/2002, 12h36
  4. [BCB5] Utilisation des Ressources (.res)
    Par Vince78 dans le forum C++Builder
    Réponses: 2
    Dernier message: 04/04/2002, 16h01
  5. Réponses: 2
    Dernier message: 20/03/2002, 23h01

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