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 :

Template de class et signature de fonction


Sujet :

Langage C++

  1. #1
    Membre actif
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 15
    Par défaut Template de class et signature de fonction
    Bonjour à tous,

    Aujourd'hui j'ai un soucis avec l'utilisation des templates, voici d'abord mon code :
    Matrix.h
    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
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    #include <vector>
    #include <iostream>
     
    #ifndef MATRIX
    #define MATRIX
     
    template<typename T> 
    class Matrix 
    {
      private:
        std::vector<std::vector<T> > data;    
     
      public:  
        Matrix();
     
        Matrix(int swidth, int sheight);
        Matrix(int size);
     
        int getWidth() { return data.size(); }
        int getHeight() { return data.size() == 0 ? 0 : data[0].size(); }
     
        void print();    
     
        ~Matrix();
    };
    #endif
    Matrix.cpp (simplifié)
    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
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    #include "Matrix.h"
     
    /*********************************
        C O N S T R U C T O R S
    **********************************/
     
    template<class T> 
    Matrix<T>::Matrix(){
      data.empty();
      std::clog << "Construction matrice" << std::endl;
    }
     
    template<class T> 
    Matrix<T>::Matrix(int swidth, int sheight) {
      data.resize(0);
      if(swidth > 0 && sheight > 0) {
        data.resize(swidth);
        for(unsigned int i = 0; i < data.size(); i++) {
          data[i].resize(sheight);
        }
        std::clog << "Construction matrice" << std::endl;
      }
    }
     
    template<class T> 
    Matrix<T>::Matrix(int size) {
      if(size > 0) {
        data.resize(size);
        for(unsigned int i = 0; i < data.size(); i++) {
          data[i].resize(size);
        }
      } else {
        data.resize(0);
      }
      std::clog << "Construction matrice" << std::endl;
    }
     
     
     
    /*********************************
              O T H E R
    **********************************/
    template<class T> 
    void Matrix<T>::print() {
      int height;
      height = data.size() == 0 ? 0 : data[0].size();
     
      std::cout << "Width = " << height << " height = "<< data.size() << std::endl;
     
      for(unsigned int i = 0; i < data.size(); i++) {
          for (unsigned int j = 0; j < data[i].size(); j++) {
            std::cout << data[i][j] << " ";
          }
          std::cout << std::endl;
       }
    }
     
     
     
    /*********************************
         D E S T R U C T O R
    **********************************/
     
    template<class T> 
    Matrix<T>::~Matrix() {
      data.resize(0);
      std::clog << "Destruction matrice" << std::endl;
    }
    Et enfin le main.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #include <iostream>
    #include "Matrix.h"
     
    int main() {
      Matrix<int> m1(5);
     
      return 0;
    }
    Voici ce me renvoie le compilateur (g++) :
    Code Console : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    main.o: In function `main':
    /home/isen/Cours/C/perso/matrix/main.cpp:5: undefined reference to `Matrix<int>::Matrix(int)'
    /home/isen/Cours/C/perso/matrix/main.cpp:5: undefined reference to `Matrix<int>::~Matrix()'
    collect2: ld a retourné 1 code d'état d'exécution
    make: *** [matrix] Erreur 1

    Il ne semble pas reconnaître les fonctions, cela ne marche pas non plus avec m1.print();. Je dois mal utiliser les templates mais même après avoir cherché je ne trouve pas de solutions.

    PS : Si je n'écrit pas template<class T> void Matrix<T>::print()(...) dans le Matrix.cpp, le compilateur me cri dessus alors que cette fonction se moque royalement du type T. Je ne vois pas pourquoi je dois écrire cela.

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    118
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 118
    Par défaut
    La définition des méthodes d'une classe template doivent être AUSSI dans le fichier.h où est déclarée la classe, voir faq C++.

  3. #3
    Membre actif
    Profil pro
    Inscrit en
    Juillet 2009
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2009
    Messages : 15
    Par défaut
    Merci backlash pour cette réponse rapide. Je trouve ca vraiment moche de mettre tout dans le .h il n'y a pas une autre solution ?

  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
    Salut,

    Il est tout à fait possible de "scinder" les différentes partie du fichier en un nombre quelconque de fichiers différents, mais il faut alors prendre certaines précautions.

    Tu peux, par exemple, créer un fichier "declaration" et un fichier "implémentation", mais qui sont toujours à considérer comme fichiers d'en-tête sous une forme proche de
    Matrix_decl.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
    #ifndef MATRIX_DECL_HPP
    #define MATRIX_DECL_HPP
    template<typename T> 
    class Matrix 
    {
      private:
        std::vector<std::vector<T> > data;    
     
      public:  
        Matrix();
     
        Matrix(int swidth, int sheight);
        Matrix(int size);
     
        int getWidth() ;
        int getHeight();
     
        void print();    
     
        ~Matrix();
    };
     
    #endif // MATRIX_DECL_HPP
    Matrix_impl.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
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    #ifndef MATRIX_IMPL_HPP
    #define  MATRIX_IMPL_HPP
    /* !!!! les fonctions template DOIVENT etre déclarées inline, de manière
     * implicites ou explicites !!! 
     */
    template<class T> 
    inline Matrix<T>::Matrix(){
      data.empty();
      std::clog << "Construction matrice" << std::endl;
    }
     
    template<class T> 
    inline Matrix<T>::Matrix(int swidth, int sheight) {
      data.resize(0);
      if(swidth > 0 && sheight > 0) {
        data.resize(swidth);
        for(unsigned int i = 0; i < data.size(); i++) {
          data[i].resize(sheight);
        }
        std::clog << "Construction matrice" << std::endl;
      }
    }
     
    template<class T> 
    inline Matrix<T>::Matrix(int size) {
      if(size > 0) {
        data.resize(size);
        for(unsigned int i = 0; i < data.size(); i++) {
          data[i].resize(size);
        }
      } else {
        data.resize(0);
      }
      std::clog << "Construction matrice" << std::endl;
    }
     
    template<class T> 
    inline void Matrix<T>::print() {
      int height;
      height = data.size() == 0 ? 0 : data[0].size();
     
      std::cout << "Width = " << height << " height = "<< data.size() << std::endl;
     
      for(unsigned int i = 0; i < data.size(); i++) {
          for (unsigned int j = 0; j < data[i].size(); j++) {
            std::cout << data[i][j] << " ";
          }
          std::cout << std::endl;
       }
    }
     
     
    template<class T> 
    inline Matrix<T>::~Matrix() {
      data.resize(0);
      std::clog << "Destruction matrice" << std::endl;
    }
     
    #endif // MATRIX_IMPL_HPP
    Il faudra alors s'assurer le la déclaration apparaisse systématiquement AVANT la définition des fonctions, ce qui implique qu'il faudra systématiquement inclure le fichier Matrix_decl.hpp avant le fichier Matrix_impl.hpp!

    L'idéal est donc peut etre de rajouter un troisième fichier qui inclut les deux fichiers précédents dans l'ordre et qui prendrait la orme de

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #ifndef MATRIX_HPP
    #define MATRIX_DECL_HPP
    #include <Matrix_decl.hpp>
    #include <Matrix_impl.hpp>
    #endif // MATRIX_HPP
    Tu constatera malgré tout que cela ne revient à rien d'autre que de... déplacer dans deux fichiers ce que l'on trouve d'habitude dans un seul...

    Je te laisse seul juge de l'utilité éventuelle de la chose
    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 é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
    Il est courant, pour le fichier d'implémentation, d'avoir une extension *.tpp.

  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 oodini Voir le message
    Il est courant, pour le fichier d'implémentation, d'avoir une extension *.tpp.
    ou *.ipp ou... n'importe quelle extension qui ne soit pas déjà d'office réservée à un type de fichier particulier :d
    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

Discussions similaires

  1. Fonction template et classe virtuelle
    Par Trademark dans le forum Langage
    Réponses: 5
    Dernier message: 25/11/2011, 19h30
  2. Syntaxe fonction template dans classe template
    Par Aleph69 dans le forum C++
    Réponses: 6
    Dernier message: 15/07/2011, 15h32
  3. Réponses: 4
    Dernier message: 15/10/2008, 09h33
  4. Réponses: 3
    Dernier message: 08/07/2008, 15h06
  5. Fonction template et classe exportée
    Par xwindoo dans le forum Langage
    Réponses: 35
    Dernier message: 11/01/2008, 21h28

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