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

Autres éditeurs Discussion :

Problèmes de fonctions membres de classe templates, gcc3.3.6


Sujet :

Autres éditeurs

  1. #1
    Futur Membre du Club
    Inscrit en
    Octobre 2005
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 6
    Points : 5
    Points
    5
    Par défaut Problèmes de fonctions membres de classe templates, gcc3.3.6
    Bonjour à tous,

    je ne sais plus quoi chercher pour utiliser une fonction membre d'une classe template sans que le linker ne râle. Je n'arrive pas à linker (mais bien à compiler) le code suivant :
    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
    #ifndef MAILLON_HPP
    #define MAILLON_HPP
     
    template <class T>
    class Maillon {
     
    private:
      T data;
      Maillon<T> *suivant;
     
     
    public:
      Maillon();
      ~Maillon();
    };
     
     
    #endif //MAILLON_HPP
    (maillon.hpp)

    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
    #include <iostream>
    using namespace std;
     
    #include "maillon.hpp"
     
     
    template <class T> Maillon<T>::Maillon()
    {
      cout << "constructeur de maillon" << endl;
      suivant = NULL;
    }
     
    template <class T> Maillon<T>::~Maillon()
    {
      delete suivant;
      suivant = NULL;
    }
    (maillon.cpp)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    #include "maillon.hpp"
     
    int main()
    {
      Maillon<int> m;
      return 0;
    }
    (client.cpp)

    g++ -c maillon.cpp ==> OK
    g++ -c client.cpp ==> OK
    g++ client.o maillon.o ==> compile mais ne linke pas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    client.o(.text+0x17): In function `main':
    : undefined reference to `Maillon<int>::Maillon[in-charge]()'
    client.o(.text+0x22): In function `main':
    : undefined reference to `Maillon<int>::~Maillon [in-charge]()'
    collect2: ld returned 1 exit status

    Par contre, lorsque je remplace maillon.cpp par :
    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
    #include <iostream>
    using namespace std;
     
    #include "maillon.hpp"
     
     
    Maillon<int>::Maillon()
    {
      cout << "constructeur de maillon" << endl;
      suivant = NULL;
    }
     
    Maillon<int>::~Maillon()
    {
      delete suivant;
      suivant = NULL;
    }
    Eh bien là, ô miracle, ça linke (mais ça n'est plus un vrai beau template)......

    je suis preneur si vous avez une idée, merci à vous !

    P.S. : que veut dire "in-charge" ?

  2. #2
    sas
    sas est déconnecté
    Membre éprouvé

    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    54
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 54
    Points : 1 257
    Points
    1 257
    Par défaut
    il ne faut pas séparer la déclaration et la définition d'un template de la même manière qu'une classe ordinaire, regroupe-les et ton code compilera.

    par exemple :

    maillon.hpp
    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
     
    #ifndef MAILLON_HPP
    #define MAILLON_HPP
     
    #include <iostream>
     
    template <class T>
    class Maillon {
     
    private:
      T data;
      Maillon<T> *suivant;
     
     
    public:
      Maillon();
      ~Maillon();
    };
     
     
    template <class T> Maillon<T>::Maillon()
    {
      std::cout << "constructeur de maillon" << std::endl;
      suivant = NULL;
    }
     
    template <class T> Maillon<T>::~Maillon()
    {
      delete suivant;
      suivant = NULL;
    }
     
    #endif //MAILLON_HPP
    main.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    #include "maillon.hpp"
     
    int main()
    {
      Maillon<int> m;
     
      return 0;
    }
    plus d'info dans la faq.

  3. #3
    Membre confirmé
    Profil pro
    Enseignant
    Inscrit en
    Avril 2004
    Messages
    440
    Détails du profil
    Informations personnelles :
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2004
    Messages : 440
    Points : 451
    Points
    451
    Par défaut
    Si tu veux garder ta configuration bien pratique de séparer les .h et les .cpp, tu peux faire un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #include "MonFichier.cpp"
    dans le .hpp....

    A+
    "Cultiver les sciences et ne pas aimer les hommes, c'est allumer un flambeau et fermer les yeux." Proverbe chinois

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 394
    Points : 473
    Points
    473
    Par défaut
    C'est bien de séparer déclaration et implémentation, mais utiliser la même
    extension pour du code source et pour la définition de template c'est dangereux.
    Souvent l'extension '.tcc' est utilisée pour cela.

  5. #5
    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 : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920

  6. #6
    Futur Membre du Club
    Inscrit en
    Octobre 2005
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 6
    Points : 5
    Points
    5
    Par défaut
    Tout d'abord, merci infiniment à tous ceux qui ont répondu, vos réponses sont très pertinentes ! Merci également pour le coup de la faq (je n'avais pas trouvé avant avec google, bien que j'aie cherché longtemps !). On ne m'y reprendra plus

    Mais la solution de tout mettre dans le .h ne me satisfait pas complètement, parce que contraire aux principes de la compilation séparée.

    Donc, j'aimerai laisser les implémentations de fonctions membres dans un fichier à part. Vous m'avez parlé de .tcc, mais j'ai aussi trouvé .tpp ailleurs. Je crois que j'envisage de garder .hpp, .cpp et .tpp pour des questions d'homogénéité. C'est pas contraire à quelque chose j'espère ?

    Maintenant, la question de la façon de faire :
    • - tout mettre dans le .hpp => pas terrible à mon avis (on pourrait corriger la FAQ ?)
      - inclure le .tpp dans le .hpp et vice versa => bof, qu'en pensez-vous ? On croise un peu les include là...
      - inclure le .hpp dans le .tpp, puis inclure le .tpp dans le main => ???
      - include le .tpp ET le .hpp dans le main => ???


    Quelle est la meilleure façon de faire à votre avis ? Je tiens à prendre de bonnes habitudes tant que je n'y connais rien

    Merci d'avance !

  7. #7
    Futur Membre du Club
    Inscrit en
    Octobre 2005
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 6
    Points : 5
    Points
    5
    Par défaut
    Ou bien tout mettre dans le .tpp ? (comme expliqué ici : http://www.cplusplus.com/doc/tutorial/tut5-1.html à la fin de la page ?)

    Help

  8. #8
    Membre confirmé
    Profil pro
    Enseignant
    Inscrit en
    Avril 2004
    Messages
    440
    Détails du profil
    Informations personnelles :
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : Avril 2004
    Messages : 440
    Points : 451
    Points
    451
    Par défaut
    inclure le .tpp dans le .hpp et vice versa => bof, qu'en pensez-vous ? On croise un peu les include là...
    Tu peux le faire tant que tu gères bien les #ifndef / #define / #endif dans chaque fichier.

    Le plus simple et le plus homogène au reste est d'inclure le .cpp (ou .tpp pour les puristes) dans le .hpp !

    Quant à donner une extension en tpp au lieu de cpp, moi je trouve ça bien inutile, puisque d'un point de vue extérieur ça revient à la même chose (même si les fonctionnements internes ne sont pas les mêmes) et que justement le but d'une programmation haut niveau est de s'éloigner au max des contraintes de plus bas niveau...

    A+
    "Cultiver les sciences et ne pas aimer les hommes, c'est allumer un flambeau et fermer les yeux." Proverbe chinois

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 394
    Points : 473
    Points
    473
    Par défaut
    Citation Envoyé par yves.dessertine
    Mais la solution de tout mettre dans le .h ne me satisfait pas complètement, parce que contraire aux principes de la compilation séparée.
    Les instances dérivées des templates sont compilées dans chaques unité de compilation
    qui les utilises. A ma connaissance, aucun compilateur ne permet à ce jour l'export
    d'instance de template, bien que cela fasse un bail qu'on en parle.

    En d'autres termes, tu ne peux pas compiler séparément une classe template.

    Quand à inclure le fichier de définition (tcc ou autre) dans le fichier d'entête, bof.
    S'il n'y a aucun besoin de séparer l'entête de la définition, je ne vois pas pourquoi le faire.
    Cette séparation n'est dûe qu'au mécanisme de compilation séparée pour ce qui est des
    fichiers classique. Je ne vois pas pourquoi s'encombrer d'un tel mécanisme.

    Pour moi, il y a un seul cas ou pour un template il faille séparer déclaration et définition. C'est quand deux classes templates sont clientes l'une de l'autre.
    Dans ce cas, effectivement, le compilateur doit pouvoir disposer des déclaration des deux, avant de parcourir leur définitions.
    Pour le reste, c'est s'encombrer de fichiers supplémentaires, qui impliquent un surcout
    de maintenance inutile.

  10. #10
    Expert éminent sénior

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 751
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 751
    Points : 10 670
    Points
    10 670
    Billets dans le blog
    3
    Par défaut
    Citation Envoyé par yves.dessertine
    Mais la solution de tout mettre dans le .h ne me satisfait pas complètement, parce que contraire aux principes de la compilation séparée.
    sauf que tu n'as pas vraiment le choix, car un template ça se compile pas tel quel, il faut d'abord l'instancier. C'est du méta code, qui sert à la génération de code qui lui est compilé... c'est pour ça qu'on a besoin de tout son contenu, car tel quel y'a rien de compilable. C'est comme vouloir compiler une macro.
    Y'a le mot clé export que le compilo Comeau supporte, mais à part celui là...

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Novembre 2003
    Messages
    394
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2003
    Messages : 394
    Points : 473
    Points
    473
    Par défaut
    Il en fait quelque chose du 'export' Comeau ?
    Parce que beaucoup de compilo l'acceptent ce mot clef, il me semble même qu'il fait
    partie du standard. Mais, la plupart l'ignore.

  12. #12
    Expert éminent sénior
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 275
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 275
    Points : 10 985
    Points
    10 985
    Par défaut
    Dans le désordre.

    - Avec les templates, il est courant et attendu de faire en sorte que l'inclusion des déclarations (typiquement .h, .hpp, .hxx, ...) charge aussi les définitions. Tu peux tout mélanger à la Java (avec un bon éditeur de texte capable de replier (-> to fold), cela passe tout seul), tu peux avoir ton .h qui inclue les définitions inlinées, ...

    - Avoir des définitions de templates déplacées dans un .cpp n'est pas un problème de puritanisme, c'est un problème pratique. Il existe diverses chaines de compilations qui traiteront automatiquement le .cpp comme un fichier à compiler (VC, gmake, ...). Or, c'est justement ce qu'il ne faut surtout pas faire.

    - Export est supporté par les compilos reposant sur le produit d'EDG -> comeau, intel, et un autre je crois. Ceci dit, je ne sais plus si il n'y avait pas eu des variations dans le support du bestio.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  13. #13
    Futur Membre du Club
    Inscrit en
    Octobre 2005
    Messages
    6
    Détails du profil
    Informations forums :
    Inscription : Octobre 2005
    Messages : 6
    Points : 5
    Points
    5
    Par défaut
    Merci à vous tous !!

    Si nos profs nous expliquaient les choses aussi bien, ça serait vraiment le bonheur !

    Je comprends tous vos points de vue. Finalement c'est vrai que séparer déclaration et implémentation n'a pas d'intérêt dans le cas des templates (je n'ai que GCC/G++, donc voilà). À part celui d'éditer des fichiers séparés...

    J'ai opté pour des fichier .tpp mélant déclatations (prototypes) de classes et impémentations, à inclure (comme ça ils ne risquent pas d'être traités comme des modules par les règles génériques de make). D'ailleurs, même Emacs ne les reconnait pas par défaut comme du C++

    --
    Yves, nouveau fan qui va essayer d'aider les autres dans la limite de ses connaissances.

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

Discussions similaires

  1. Spécialisation de méthode membre de classe template
    Par Zbouirf dans le forum Langage
    Réponses: 3
    Dernier message: 23/07/2008, 02h30
  2. pthread_create et fonction membre de classe
    Par mamelouk dans le forum SL & STL
    Réponses: 6
    Dernier message: 10/10/2007, 15h47
  3. [POO] Problème de chargement d'une classe template
    Par shensi dans le forum Langage
    Réponses: 5
    Dernier message: 04/08/2007, 15h50
  4. S.O.S : Fonctions membres et classes dérivées
    Par akira44 dans le forum C++
    Réponses: 3
    Dernier message: 26/06/2007, 20h53
  5. Réponses: 8
    Dernier message: 18/06/2007, 15h06

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