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 :

Forward Declaration et template


Sujet :

C++

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 17
    Par défaut Forward Declaration et template
    Bonjours,
    // b.h
    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
     
    template<class T>
    class A;
     
    class B
    {
        void function(A<double>& );
    }
     
    //b.cpp
     
    void B::function(A<double>& a)
    {
         a.fonctionQuelconque();
    }
    Mon problème est quand je fais une déclaration forward d'une template, le compilateur n'arrive pas à accéder au fonction de cette classe, du moins c'est mon cas. Est ce normale ?

  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,
    Citation Envoyé par Zakaima Voir le message
    Bonjours,
    // b.h
    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
     
    template<class T>
    class A;
     
    class B
    {
        void function(A<double>& );
    }
     
    //b.cpp
     
    void B::function(A<double>& a)
    {
         a.fonctionQuelconque();
    }
    Mon problème est quand je fais une déclaration forward d'une template, le compilateur n'arrive pas à accéder au fonction de cette classe, du moins c'est mon cas. Est ce normale ?
    Oui, bien sur...

    Quand tu écris
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    template <typename T>
    class A;
    tu dis au compilateur "ne t'en fais pas de trouver A<XXX> dans le code, je t'assure que c'est quelque chose qui existe.

    Le problème, c'est que tu ne fais rien d'autre que de décalrer le fait qu'il existe une classe (template) nommée A.

    Pour que le compilateur puisse utiliser le contenu de la classe A, il doit connaitre ce contenu, et, pour y arriver, il a besoin de la définition de la classe (en gros de l'inclusion du fichier d'en-tête dans lequel la classe est définie)

    Dans le B.h, tu peux donc effectivement te contenter de la déclaration anticipée (juste pour que le compilateur sache que la classe A existe), mais dans B.cpp, tu as besoin de la définition complète
    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 averti
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 17
    Par défaut
    Donc dans mon cas il est plus intéressant de faire un include que une forward declaration ?

  4. #4
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    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
    //b.h
    template<class T>
    class A;
    
    class B
    {
        void function(A<double>& );
    }
    
    //b.cpp
    #include A.h
    void B::function(A<double>& a)
    {
         a.fonctionQuelconque();
    }
    Dans les entêtes, la déclaration anticipée est mieux (moins de dépendances...)
    Mais quand le code est requis, il faut les inclusions.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 17
    Par défaut
    Merci pour l'explication,

    j'essaye d'améliorer ma façon d'inclure mes fichier, de pouvoir le faire de la façon la plus intelligente et optimale. Sur internet j'ai lu ceci :

    - do nothing if: A makes no references at all to B
    - do nothing if: The only reference to B is in a friend declaration
    - forward declare B if: A contains a B pointer or reference: B* myb;
    - forward declare B if: one or more functions has a B object/pointer/reference
    as a parementer, or as a return type: B MyFunction(B myb);
    - #include "b.h" if: B is a parent class of A
    - #include "b.h" if: A contains a B object: B myb;

    Mais en générale quand on fait une référence à une classe dans une autre on utilise quasiment toujours c'est fonction membres. Donc les forward déclaration deviennent très peu utile ?

  6. #6
    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 Zakaima Voir le message
    Mais en générale quand on fait une référence à une classe dans une autre on utilise quasiment toujours c'est fonction membres. Donc les forward déclaration deviennent très peu utile ?
    C'est en général dans des .h(pp), là où il n'y a souvent pas d'implémentations (sauf en cas d'utilisations de templates), qu'elles se révèlent très utiles.
    Si tes .h(pp) ont des inclusions inutiles, et que ces mêmes .h(pp) sont inclus dans de nombreux fichiers, elles deviennent de précieux alliés pour réduire les temps de compilation.

  7. #7
    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 Zakaima Voir le message
    Merci pour l'explication,

    j'essaye d'améliorer ma façon d'inclure mes fichier, de pouvoir le faire de la façon la plus intelligente et optimale. Sur internet j'ai lu ceci :

    - do nothing if: A makes no references at all to B
    - do nothing if: The only reference to B is in a friend declaration
    - forward declare B if: A contains a B pointer or reference: B* myb;
    - forward declare B if: one or more functions has a B object/pointer/reference
    as a parementer, or as a return type: B MyFunction(B myb);
    - #include "b.h" if: B is a parent class of A
    - #include "b.h" if: A contains a B object: B myb;

    Mais en générale quand on fait une référence à une classe dans une autre on utilise quasiment toujours c'est fonction membres. Donc les forward déclaration deviennent très peu utile ?
    La déclaration anticipée permet, comme je l'ai expliqué, uniquement au compilateur de savoir qu'il existe un symbole nommé <nom_de_la_classe>.

    De cette manière, il ne s'inquiètera pas de trouver ce symbole comme nom de type pour un argument, par exemple.

    L'idéal reste de recourir à la déclaration anticipée "chaque fois que possible", c'est à dire:
    Tant que tu n'as pas besoin de connaitre le contenu de la classe par exemple:
    1. Quand tu veux déclarer une fonction qui prend en argument une référence ou un pointeur sur un objet du type concerné
    2. Quand tu veux déclarer un membre qui est un pointeur ou une référence sur un objet du type concerné

    En effet, si tu rajoutes tout simplement les fichiers d'en-tête de tous les types dont ta classe a besoin, il t'arrivera régulièrement d'être confronté à un problème de dépendances circulaires : un fichier d'en-tête XXX.h qui a besoin du fichier d'en-tête YYY.h qui a lui-même besoin du fichier XXX.h de manière directe ou indirecte

    De plus, il faut savoir que le préprocessing des fichiers d'en-tête est un processus qui prend énormément de temps, et qu'il n'est pas rare de trouver un fichier AAA.h qui inclut un fichier BBB.h qui inclut lui-même un fichier CCC.h qui inclut...(on peut continuer longtemps comme ca ) et que tous les fichiers doivent alors être préprocessés.

    Il et d'autant plus dommage d'avoir 150 fichier à préprocesser si tout ce qui nous intéresse, dans le cas d'une classe AAA, c'est de pouvoir savoir qu'une classe XXX dispose de la fonction doIt() (seule fonction de XXX réellement utilisée dans le code de AAA )

    Par contre, il n'y a en effet pas le choix : la déclaration anticipée permet de retarder le moment où l'incluision du fichier sera nécessaire, mais il faudra bien que le compilateur sache, à un moment ou à un autre, que la fonction doIt() fait bel et bien partie de l'interface de la classe XXX pour accepter (après avoir vérifier la concordance de type des éventuels argument) le fait que l'on fasse appel à cette fonction


    A ce moment là, l'inclusion du fichier d'en-tête devient incontournable
    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

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2010
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 17
    Par défaut
    Merci beaucoup pour vos explications la chose devient plus claire !

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

Discussions similaires

  1. Forward declaration avec templates
    Par gbdivers dans le forum Langage
    Réponses: 2
    Dernier message: 06/01/2011, 12h49
  2. forward declaration sous template
    Par Kurisu dans le forum Langage
    Réponses: 9
    Dernier message: 15/08/2008, 22h58
  3. Probleme de forward declaration
    Par vandamme dans le forum Bibliothèques
    Réponses: 0
    Dernier message: 05/10/2007, 18h16
  4. Probleme de forward declaration
    Par porco dans le forum C++
    Réponses: 2
    Dernier message: 15/10/2006, 17h15
  5. has incomplete type,forward declaration of ,
    Par Pragmateek dans le forum C++
    Réponses: 12
    Dernier message: 22/07/2006, 15h03

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