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 :

detecter qu'une classe est abstraite


Sujet :

C++

  1. #1
    Futur Membre du Club
    Inscrit en
    Mai 2007
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 13
    Points : 6
    Points
    6
    Par défaut detecter qu'une classe est abstraite
    Bonjour,

    j'ai fais un générateur qui créent des fichiers .h et des .cpp, dans ces fichiers je fais un certain traitement pour les classes de ma librairie, et à un certain moment dans mon code généré il ya un "new Maclasse", pour les classes abstraites j'ai des erreurs de compils,
    est ce que je peux detecter qu'une classe est abstraite pour adapter le code à générer dans ce cas.

    j'espere que j'ai été clair et merci pour votre aide.

  2. #2
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 262
    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 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Peux-tu analyser ton .h pour savoir si la classe contient au moins une fonction virtuelle pure?
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  3. #3
    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

  4. #4
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 363
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 363
    Points : 20 394
    Points
    20 394
    Par défaut
    1-c'est en runtime intrinséquement qu'on va détecter si la classe est abstraite ou non.
    Là c'est radicalement différent c'est de l'analyse de texte.

    2-Et si je n'utilise pas boost ?

    Comme le dit R0d il faut détecter la présence du mot clé "vitual"

  5. #5
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 262
    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 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    En réalité c'est un peu plus compliqué que cela. Pour qu'une classe soit abstraite, et qu'elle ne puisse donc pas être instanciée, elle doit contenir au moins une fonction virtuelle pure. Il faut donc détecter le mot-clé virtual et le =0.

    Mais bon, nous ne connaissons rien du contexte.
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  6. #6
    Futur Membre du Club
    Inscrit en
    Mai 2007
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 13
    Points : 6
    Points
    6
    Par défaut
    dans mon cas, je parse le .h de la classe donc avec qlq modifications je peux detecter la declaration d'une méthode virtuelle pure, j'ai aussi boost dans mon environnement je vais creuser un peu ces 2 pistes et je vous reviens, merci pour vos propositions

  7. #7
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    1-c'est en runtime intrinséquement qu'on va détecter si la classe est abstraite ou non.
    Là c'est radicalement différent c'est de l'analyse de texte.
    C'est détecté à la compilation.

    Pour qu'une classe soit abstraite, et qu'elle ne puisse donc pas être instanciée, elle doit contenir au moins une fonction virtuelle pure
    Une classe ne possédant que des constructeurs protégés sera également abstraite, si on considère qu'une classe abstraite est une classe qui ne peut être instanciée.

  8. #8
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 262
    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 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Laurent Gomila
    Une classe ne possédant que des constructeurs protégés sera également abstraite, si on considère qu'une classe abstraite est une classe qui ne peut être instanciée.
    Exact.
    Il y a aussi le cas suivant:
    Code c++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    class A
    {
    public:
       virtual void f() = 0;
    };
     
    class B : A
    {
    };
     
    class C : B
    {
    public:
       void f(){/*fait quelque chose*/}
    };
    Dans l'exemple ci-dessus, B est considérée comme abstraite car elle ne peut pas être instanciée (à cause de f() qui reste virtuelle pure au sein de B).
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

  9. #9
    Futur Membre du Club
    Inscrit en
    Mai 2007
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 13
    Points : 6
    Points
    6
    Par défaut
    oui avec ces cas, et peut etre qu'il y en a d'autres par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class A {
      virtual void f() =0;
      virtual void g() =0;
    };
     
    class B : public A{
      virtual void f() { /*traitement*/ }
    };
     
    class C : public B {
      virtual void f() { /*traitement*/ }
      virtual void g() { /*traitement*/ }
    };
    on peut pas faire un new B.

    c'est complexe de detecter si on peux faire new B ou pas.
    j'ai testé boost, j'ai pas la bonne version du compilateur.

    qlq aurais t'il des idées ?

    Merci.



    balises [code] rajoutées par r0d. Merci d'y penser.

  10. #10
    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
    Mat.M : aucune des structures de Boost.Typetraits ne donne des informations qu'à l'exécution. Tout est fait pour donner des infos à la compilation.

    C'est pourquoi je l'ai suggéré. De plus, ce n'est qu'un header, rien à lier. Il suffit d'avoir boost d'installé.

    Est-ce que cela satisfait l'auteur ?

  11. #11
    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
    Comment ça tu n'as pas la bonne version ?
    Boost est cross-compiler, pour peu que ton compilateur ne soit pas de l'âge de pierre. Quel est ton compilo ?

  12. #12
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    is_abstract requiert qu'une certaine technique soit implémentée, ce qui n'est le cas qu'à partir de VC 7.1 ou gcc 3.3 si je me souviens bien.

  13. #13
    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
    Oui c'est sur qu'avec VC6 ça passera pas.
    Mais bon, pour peu qu'il n'y ait pas une restriction trop sévère sur le compilo, il n'y a pas de problème.

  14. #14
    Futur Membre du Club
    Inscrit en
    Mai 2007
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 13
    Points : 6
    Points
    6
    Par défaut
    ma version du compilo est CC 6.12, is_astract se comporte comme is_polymorphic qui est un comportement erroné dans mon cas.

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

    Informations professionnelles :
    Activité : aucun

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

    Pour ce qui concerne les classes abstraites parce que leur constructeur est protected, la seule solution, si tu ne peux utiliser boost, consiste à vérifier si les classes dérivées ont un constructeur publique et si elles appellent (par liste d'initialisation ) le constructeur de la classe de base.

    Pour ce qui concerne les classes abstraites du fait de la présence de fonctions virtuelles pures, le plus logique serait, peut etre, de maintenir une liste des fonctions virtuelles pures rencontrées dans la classe de base.

    Tu maintiendrais également une liste des fonctions déclarées dans la classe dérivée.

    La vérification pourrait alors prendre une forme qui vérifierait que toutes les fonctions présentes dans la liste des fonctions virtuelles pure de la classe de base soient redéclarées dans la classe dérivée:

    Si c'est le cas, la classe dérivée est instanciable, sinon, c'est elle meme une classe abstraite

    Tu pourrais donc avoir une classe de lecture qui pourrait prendre à peu pres cette forme:
    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
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
     
    class ClasseLue
    {
        public:
            ClasseLue(/*...*/);
            ~ClasseLue();
            bool IsBase(); const /* permet de savoir si on a affaire à une classe
                                  * de base */
            bool IsAbstract() const;/* pour les classes de bases */
            bool IsAbstract(const ClasseLue& base) const;/* pour les classes 
                                                          * dérivées */
            bool MethodExists(const string& proto) const /* vérifie si une fonction 
                                                          * est déclarée */
            const vector<string> AllVirtualPures() const;/* pour récupérer 
                                       * la liste des fonctions virtuelles pures */
            /* tout le reste */
        private:
            vector<CTors> ctors;/* liste des constructeurs */
            string dtors;/* le destructeurs */
            vector<Method> methods;/* liste des fonctions */
            vector<string> virtualpures; /* juste les prototypes des fonctions 
                                          * virtuelles pures */
            bool isbase;
            /* tout le reste */
    };
    bool ClasseLue::IsBase() const{return isbase;}
    const vector<string> AllVirtualPures() const{return virtualpures;}
    bool ClasseLue::IsAbstract() const 
    {
        /* D'abord, vérifier si les constructeurs sont tous protected */
        bool areprotected=true;
        for(size_t i=0;i<ctors.size();i++)
            if(!ctors[i].IsProtected())
                areprotected=false;
        /* renvoyer vrai si tous les constructeurs sont protected ou si on a au
         * minimum une fonction virtuelle pure */
        return areprotected | virtualpurs.size()>0;
    }
    bool ClasseLue::IsAbstract(const ClasseLue& base) const
    {
        /* une idée parmis tant d'autres */
        vector<string> virutalbase=base.AllVirtualPures();
        size_t basecount=virtualbase.size();
        /* Pour chacune des classes virtuelles pures redéfinies dans
         * la classe dérivées, on décréemente le compteur
         */
        for(size_t i=0;i<virtualbase.size();i++)
            if(MethodExists(virtualbase[i])
                --basecount;
        /* Renvoie vrai si la classe dérivée est elle-meme abstraite ou si il reste
         * ne serait-ce qu'une seule fonction virtuelle pure non redéclarée */
        return basecount>0 | IsAbstract();
    }
    Nota:
    Certaines informations sont peut etre manquantes:

    • IsProtected() serait une méthode permettant de déterminer si une fonction membre a une visibilité "protected"
    • Il reste de ta responsabilité, lorsque tu rajoute une méthode, de vérifier si elle est virtuelle pure, et, si c'est le cas, d'en rajouter son prototype dans le vector "virtualpures"
    • Pour chaque fonction membre, il serait utile de pouvoir en récupérer le prototype, et de s'en servir pour chercher si une fonction est déclarée dans MethodExists
    • Je n'ai pas pris en compte les héritages multiples
    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

  16. #16
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 363
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 363
    Points : 20 394
    Points
    20 394
    Par défaut
    Citation Envoyé par Laurent Gomila
    C'est détecté à la compilation.
    Je suis bien d'accord mais c'est lui qui fait l'interprétation du fichier ( du moins écrire le code pour ) pas le compilateur ou je n'ai rien pigé

  17. #17
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Honêtement je ne sais pas du tout comment il s'y prend (est-ce qu'il l'a clairement expliqué ?), mais je pense que tu as raison. C'était juste pour te corriger que j'ai fait cette petite remarque

  18. #18
    Futur Membre du Club
    Inscrit en
    Mai 2007
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 13
    Points : 6
    Points
    6
    Par défaut
    je pense que la reponse de koala01 est la solution pour mon probleme il faudrait maintenir une table des symboles et s'assurer de la définition des symboles de la classe abstraite dans les classes dérivés pour dire si il sont abstraites elle aussi,
    mais j'ai pas beaucoup de temps pour creuser ça donc je vais pas traiter ce problème, je déclare un #define ABSTRACT et j'ajoute ce mot dans mes déclarations de classe : class ABSTRACT A { /**/ }; ca ne change pratiquement rien au code de mon application mais je peux facilement detecter que ma classe est abstraite avec mon parseur.

    merci pour vos réponses.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 626
    Points : 30 684
    Points
    30 684
    Par défaut
    Mais comment parse tu ton fichier

    Car, finalement, tu obtiens toutes les réponses qu'il te faut :

    • au début de la classe, avant tout mot clé de visibilité (private, protected ou public), les déclarations qui suivent sont private
    • les mots clés private/protected/public s'appliquent jusqu'à ce qu'un autre mot clé de la meme famille apparaisse
    • le constructeur est la seule fonction dont le nom soit... celui de la classe
    • une fonction est virtuelle pure si elle est précédée du mot clé virtual et si sa liste de paramètres est suivie de =0 avant le ;

    Au pire, rien ne t'empeche de garder simplement, dans ta classe qui parse le fichier, un booleen hasprotectedconstructors, et tu pourrais tres bien avoir maintenir la liste des fonctions virtuelles pures sous une forme utilisant une std::map<std::string, std::vector<string> > statique, ainsi qu'un tableau statique de chaines:

    La clé serait le nom de la classe, les valeurs (ici un vecteur de chaines ) seraient le nom des fonctions virtuelles pures

    Le tableau de chaines statique servirait pour sa part à garder les noms des fonctions déclarées pour chaque classe lues: à chaque fois que tu rencontre le mot cle class dans le code, tu le vide, puis tu rajoutes les fonctions au fur et à mesure de leurs déclarations.

    Quand vient le moment de vérifier si une classe est abstraite, tu n'aurais plus quà récupérer pour chaque héritage le tableau des fonctions virtuelles pures et à le comparer avec le tableau des fonctions déclarées: si une seule fonction apparaît dans le tableau des fonctions virtuelles pures et n'apparaît pas dans le tableau des fonctions déclarée OU si le membre hasprotectedconstructors est à true, c'est que ta classe est abstraite
    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

  20. #20
    Futur Membre du Club
    Inscrit en
    Mai 2007
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Mai 2007
    Messages : 13
    Points : 6
    Points
    6
    Par défaut
    salut,
    pour parser mon fichier j'ai implémenté un automate d'analyse syntaxique selon la grammaire définis par mes besoins,.

    koala01 je suis tous à fait d'accord avec toi et je pense que ta solution resout mon problème, pour son implémention elle est assez simple dans mon cas puisque je contrôle parfaitement mon automate d'analyse et qu'il suffira d'ajouter des états pour detecter les cas cités.

    pour l'instant je laisse ca comme évol de mon projet et je vais la dévelloper dés que j'ai un peu de temps.
    Merci,

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

Discussions similaires

  1. Réponses: 14
    Dernier message: 10/02/2007, 13h27
  2. Detecter si une jvm est installée sur le poste client
    Par jpastier dans le forum Servlets/JSP
    Réponses: 2
    Dernier message: 02/02/2007, 11h43
  3. Réponses: 2
    Dernier message: 29/06/2006, 16h33
  4. [POO] Classe interne à une classe, est ce possible ?
    Par Matth_S dans le forum Langage
    Réponses: 13
    Dernier message: 10/02/2006, 10h24
  5. Detection si une BD est sollicitée
    Par Yepazix dans le forum Bases de données
    Réponses: 6
    Dernier message: 31/08/2004, 19h37

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