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 :

Héritage à la compilation


Sujet :

Langage C++

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2004
    Messages
    85
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 85
    Par défaut Héritage à la compilation
    Bonsoir à tous
    Voici une question simple.
    Soient 2 classes A et B que je ne peux modifier en rien.
    Je souhaite savoir, à la compilation, s'il existe un lien d'heritage entre elles.
    Merci

  2. #2
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    Bonjour,

    std::is_base_of du header <type_traits> si tu peux te permettre le C++11, sinon SFINAE mais ca ne te donnera que les héritages publiques.

  3. #3
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par Flob90 Voir le message
    Bonjour,

    std::is_base_of du header <type_traits> si tu peux te permettre le C++11, sinon SFINAE mais ca ne te donnera que les héritages publiques.
    Tu l'as aussi en TR1 (plus largement supporté que C++11).

    Sinon, effectivement, ça se fait assez aisément avec SFINAE:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    template <class A, class B>
    struct my_is_base_of
    {
      typedef char one[1];
      typedef char two[2];
      one check(A*);
      two check(...);
      static const bool value = (sizeof(check((B*)0)) == sizeof(one));
    }
    Si ta classe Derived dérive de Base, alors my_is_base_of<Base,Derived>::value == true ; sinon, il vaudra false. Et c'est une constante connue à la compilation (et c'est un code relativement abscons ; ben oui, mais faut ce qu'il faut).
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  4. #4
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    @Emmanuel Deloget: "aisément " Pas exactement, ce que tu fais avec SFINAE donne les relations d'héritage publique, alors que is_base_of doit donner toutes les relations d'héritage.

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2004
    Messages
    85
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 85
    Par défaut Héritage à la compilation
    Merci pour vos reponses
    Je souhaiterai préciser que si B n'hérite pas de A alors il y echec de la compilation.
    J'ai retenu une idée parmi vos réponses mais ca ne marche pas voici le code et le message d'erreur.
    Si vous avez une alternative du meme genre, je suis preneur.
    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
     
    struct A{};
    struct B:public A{};
     
    template<bool>    struct enable_if{};
    template<>         struct enable_if<true>{typedef int type; };
     
    template < class U, class V>
    struct is_base_of
    {
          static int          check(U*);
          static double     check(...); // astuce
     
          typedef typename enable_if<sizeof (check((V*) (NULL)) )==sizeof(int)>::type check_derivation;
     
    };
     
    int _tmain(int argc, _TCHAR* argv[])
    {
          is_base_of<A,B> type;type;
          return 0;
    }
    le message d'erreur précise qui ne compile pas "static int check(U*);" mais plutôt l'autre fonction.
    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
     
    1>------ Build started: Project: Stl, Configuration: Debug Win32 ------
    1>Compiling...
    1>Stl.cpp
    1>c:\tests\stl\stl\stl.cpp(28) : error C2039: 'type' : is not a member of 'enable_if<__formal>'
    1>        with
    1>        [
    1>            __formal=false
    1>        ]
    1>        c:\tests\stl\stl\stl.cpp(29) : see reference to class template instantiation 'is_base_of<U,V>' being compiled
    1>c:\tests\stl\stl\stl.cpp(28) : error C2146: syntax error : missing ';' before identifier 'check_derivation'
    1>c:\tests\stl\stl\stl.cpp(28) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
    1>c:\tests\stl\stl\stl.cpp(28) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
    1>Build log was saved at "file://c:\Tests\Stl\Stl\Debug\BuildLog.htm"
    1>Stl - 4 error(s), 0 warning(s)

  6. #6
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par Flob90 Voir le message
    @Emmanuel Deloget: "aisément " Pas exactement, ce que tu fais avec SFINAE donne les relations d'héritage publique, alors que is_base_of doit donner toutes les relations d'héritage.
    Effectivement

    Il manque une partie du message en fait. Je ne m'en suis pas rendu compte (mais en même temps, je faisais 36 choses différentes en même temps). Ca se trouve, je l'ai pensé et je ne l'ai pas écrit (c'est tout moi ça).

    La partie qui manque était grosso-modo:

    Note que ça ne fonctionne que si tu peux écrire Base* p = (Derived*)0; puisque c'est la base du principe, ce qui veut dire que cette classe ne supporte pas les héritages protégés ou privés (qui sont rares, de toute manière).
    Pour déterminer si un héritage existe et est privé, il est nécessaire de passer par le support du compilateur : __is_base_of(Base,Derived) sur g++ et Visual C++ (notons la notation fonctionnelle : ce n'est pas un template, c'est une fonction du compilateur qui intervient sur des types ; cf http://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html pour g++ et http://msdn.microsoft.com/fr-fr/library/ms177194 pour VC++ ; il est heureux que les deux vendeurs nous aient donné la même interface).

    Du coup, on peut écrire :

    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
     
    #if defined(__GNUG__) || (defined(__MSVC__) && (_MSC_VER >= 1400))
    template <class _Base, class _Derived, bool known_compiler>
    struct is_base_of<_Base, _Derived>
    {
      static const bool value = __is_base_of(_Base,_Derived);
    };
    #else
    // cas général limité
    template <class _Base, class _Derived>
    struct is_base_of
    {
      typedef char one[1];
      typedef char two[2];
      one check(_Base*);
      two check(...);
      static const bool value = (sizeof(check((_Derived*)0)) == sizeof(one));
    };
    #endif
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  7. #7
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut discussion sur les comparaisons avec sizeof
    Citation Envoyé par Math75 Voir le message
    Merci pour vos reponses
    Je souhaiterai préciser que si B n'hérite pas de A alors il y echec de la compilation.
    J'ai retenu une idée parmi vos réponses mais ca ne marche pas voici le code et le message d'erreur.
    Si vous avez une alternative du meme genre, je suis preneur.
    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
     
    struct A{};
    struct B:public A{};
     
    template<bool>    struct enable_if{};
    template<>         struct enable_if<true>{typedef int type; };
     
    template < class U, class V>
    struct is_base_of
    {
          static int          check(U*);
          static double     check(...); // astuce
     
          typedef typename enable_if<sizeof (check((V*) (NULL)) )==sizeof(int)>::type check_derivation;
     
    };
     
    int _tmain(int argc, _TCHAR* argv[])
    {
          is_base_of<A,B> type;type;
          return 0;
    }
    le message d'erreur précise qui ne compile pas "static int check(U*);" mais plutôt l'autre fonction.
    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
     
    1>------ Build started: Project: Stl, Configuration: Debug Win32 ------
    1>Compiling...
    1>Stl.cpp
    1>c:\tests\stl\stl\stl.cpp(28) : error C2039: 'type' : is not a member of 'enable_if<__formal>'
    1>        with
    1>        [
    1>            __formal=false
    1>        ]
    1>        c:\tests\stl\stl\stl.cpp(29) : see reference to class template instantiation 'is_base_of<U,V>' being compiled
    1>c:\tests\stl\stl\stl.cpp(28) : error C2146: syntax error : missing ';' before identifier 'check_derivation'
    1>c:\tests\stl\stl\stl.cpp(28) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
    1>c:\tests\stl\stl\stl.cpp(28) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
    1>Build log was saved at "file://c:\Tests\Stl\Stl\Debug\BuildLog.htm"
    1>Stl - 4 error(s), 0 warning(s)
    Tu ne peux qu'avoir une erreur de compilation, puisque enable_if<false>::type n'est pas défini - seul enable_if<true>::type l'est. C'est d'ailleurs ce que te dis le compilateur.

    Donc si A et B ne sont pas liés par une relation d'héritage, check_derivation ne peut pas exister.

    Un type trait qui cherche à déterminer si quelque chose est vrai ne peut pas utiliser la technique que tu mets en oeuvre. Le fait d'avoir un type qui est un alias sur int si une condition est vérifiée ne peut d'ailleurs pas beaucoup t'aider par la suite. Le but est d'avoir une structure qui te dis si telle ou telle relation est vraie - un static const bool fera l'affaire.

    Edit: juste un petit point : rien dans le standard ne te garanti que sizeof(int) != sizeof(double). Les tailles de sizeof(char[1]) et sizeof(char[2]), par contre, sont garanties par le standard et sont respectivement un byte et deux bytes - ce sont donc des tailles différentes.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  8. #8
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Bonjour.

    J'ajouterai que, de mémoire, enable_if est plutôt défini de cette manière :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    template <bool, typename _Tp = void>
    struct enable_if
    {};
     
    template <typename _Tp>
    struct enable_if<true, _Tp>
    { typedef _Tp type; };
    Ce qui permet d'évaluer une expression et de directement « retourner » un type si cette expression est vraie.

    Quant à is_base_of, ça correspond à l'expression à évaluer.
    C'est pourquoi il y a une variable membre de type booléen et pas un typedef.
    Donc ne modifie pas la structure proposée pas Emmanuel Deloget !

    Ça s'utilise de cette manière (par exemple) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    typename enable_if< is_base_of<A, B>::value, B >::type x
    Ainsi, la variable x est du type B si et seulement si B hérite (directement ou non) de A.
    Sinon, le compilateur n'est pas en mesure de déterminer un type pour x, et alors la compilation échoue.
    Comme discuté plus haut, la détection des héritage protégé et privé dépend de l'implémentation de is_base_of.

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2004
    Messages
    85
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 85
    Par défaut Heritage a la compilation
    merci pour vos réponses

    En fait le code que j ai envoyé, devrait fonctionner car B hérite bien de A et donc la premiere implementation de check devrait etre utilisée ce qui donne enable_if<true>, or il ne voit que la seconde meme quand j instantie is_base_of<A,A>.

    J ai décidé, pour le type de retour de check, double versus int plutôt que one versus two car sinon le compliateur me renvoie une erreur C2090; le compilateur veut un pointeur en type de retour pas un tableau.

    Je continue à regarder vos réponses
    et merci encore pour le temps consacré.

    Mathieu

  10. #10
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2004
    Messages
    85
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 85
    Par défaut Héritage à la compilation
    cette implementation simplifiée de enable_if empèche la compilation c 'est bien ce que je cherchais à faire.

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Août 2004
    Messages
    85
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 85
    Par défaut
    Je propose
    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
    template<bool>    
    struct enable_if{};
    template<>        struct enable_if<true>{typedef int type; };
    template < class U, class V>
    struct is_derivated_impl
    {
          typedef int one[1];
          typedef int two[2];
          static one &      check(U*);
          static two &      check(...); // astuce
          static const bool value = sizeof (check( static_cast<V*> (NULL)) )==sizeof(one);      //astuce
     
    };
     
    template < class U, class V>
    struct is_derivated
    {
          typedef typename enable_if<is_derivated_impl<U,V>::value>::type check_derivation;
    };
    dans le configuration suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    struct A{};
    struct B: public A{};
    struct C{};
    une instance de is_derivated<A,C> provoque une erreur de compliation alors que is_derivated<A,A> ou is_derivated<A,B> non.

  12. #12
    Membre émérite Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Par défaut
    Juste par curiosité, tu peux mettre quelques exemples d'application de is_derivated, s'il-te-plaît ?

  13. #13
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par Math75 Voir le message
    une instance de is_derivated<A,C> provoque une erreur de compliation alors que is_derivated<A,A> ou is_derivated<A,B> non.
    (mode-grammar-nazi-on)
    En anglais, dériver se dit to derive et non pas to derivate. Du coup, is_derived est certainement moins pique-les-yeux que is_derivated
    (mode-grammar-nazi-off)
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

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

Discussions similaires

  1. Héritage, template et compilation
    Par Letinono dans le forum Langage
    Réponses: 10
    Dernier message: 23/09/2011, 17h47
  2. héritage template ,compilation
    Par carton99 dans le forum Débuter
    Réponses: 2
    Dernier message: 11/04/2010, 17h46
  3. Probléme de compilation pour un héritage
    Par Mooneer dans le forum C++
    Réponses: 2
    Dernier message: 21/12/2009, 11h40
  4. Réponses: 3
    Dernier message: 31/10/2006, 09h42
  5. Réponses: 4
    Dernier message: 07/07/2005, 13h03

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