|
|
|
|
Salut.
Met nous du code concret, pasque là, tu n'es pas clair. mais disons, que tu as template <class T> class maC{ T a;} alors, dans le main, tu fait : maC<int> variable_class; quel compilateur utilise tu aussi? Salutation ! Char Snipeur |
vous voulez du code en voici ^^ :)
(intégralité du code) ce code sert a créer et géré une liste chainé. a partir d'un élément on a accé a son suivant et son précédent, et j'utilise des itérateur qui pointe vers un élément pour parcourir la liste : "liste.h" : #ifndef LISTE_H #define LISTE_H #include <string> using namespace std; template <class T> class Element; template <class R> class Iterateur; template <class S> class Liste{ private: // pointeurs vers le premier et le dernier element Element<S>* premier; Element<S>* dernier; public: //constructeurs Liste<S>(); //constructeur par recopie Liste<S>(const Liste<S> &); //fonction membre copy utilisé par le constructeur par recopie et par l'operateur d'affectation void copy(const Liste &); //destructeur ~Liste(); //fonction membre free utilisé par le destructeur et par l'operateur d'affectation void free(); Liste& operator=(const Liste&); // ajouter s a la fin de la liste void ajouter(const S& s); // ajouter s avant la position pos void inserer(const Iterateur<S>& pos, const S& s); // supprimer l'element a la position pos void supprimer(Iterateur<S>& pos); // la premiere position Iterateur<S> debut() const; // la fin de la liste (apres la derniere position) Iterateur<S> fin() const; }; template<class R> class Iterateur { public: // constructeur Iterateur(); // retourne la valeur dans cette position R& operator*() const; // avance a la position suivante void operator++(); void operator++(int); // recule a la position precedente void operator--(); void operator--(int); // compare deux iterateurs bool operator==(const Iterateur& b) const; bool operator!=(const Iterateur& b) const; private: // pointeur vers l'element courant Element<R>* position; // pointeur vers le dernier element de la liste Element<R>* dernier; template <class S> friend class Liste; }; #endif "liste.cc" : #include "liste.h" #include <string> #include <iostream> using namespace std; template <class T> class Element { public: // constructeur Element(const T& s); private: string valeur; // pointeurs vers les voisins Element<T>* precedent; Element<T>* suivant; template <class S> friend class Liste; template <class R> friend class Iterateur; }; template <class T> Element<T>::Element(const T& s) { valeur = s; precedent = suivant = NULL; } template<class R> Iterateur<R>::Iterateur() { position = dernier = NULL; } template<class R> R& Iterateur<R>::operator*() const { return position->valeur; } template<class R> void Iterateur<R>::operator++() { position = position->suivant; } template<class R> void Iterateur<R>::operator++(int inutile) { position = position->suivant; } template<class R> void Iterateur<R>::operator--() { if (position == NULL) // fin de la liste position = dernier; else position = position->precedent; } template<class R> void Iterateur<R>::operator--(int) { if (position == NULL) // fin de la liste position = dernier; else position = position->precedent; } template<class R> bool Iterateur<R>::operator==(const Iterateur& b) const { return position == b.position; } template<class R> bool Iterateur<R>::operator!=(const Iterateur& b) const { return position != b.position; } Liste::Liste() { premier = dernier = NULL; } template<class S> Liste<S>::Liste() { premier = dernier = NULL; } template<class S> Liste<S>::Liste(const Liste<S> &l){ copy(l); } template<class S> void Liste<S>::copy(const Liste<S> &l){ premier = dernier = NULL; Iterateur<S> pos; for (pos =(l.debut()); pos!=(l.fin()); pos++){ ajouter(*pos); } } template<class S> Liste<S>::~Liste(){ free(); } template<class S> void Liste<S>::free(){ Iterateur<S> pos; for (pos =debut(); pos!=fin(); pos++){ delete(pos.position); } } template<class S> Liste<S>& Liste<S>:: operator=(const Liste &l){ if(this !=&l){ free(); copy(l); } return *this; } template<class S> Iterateur<S> Liste<S>::fin() const { Iterateur<S> it; it.position = NULL; it.dernier = dernier; return it; } template<class S> void Liste<S>:: ajouter(const S& s){ Element<S> *e=new Element<S>(s); if(dernier==NULL){ dernier=premier=e; } else { e->precedent =dernier; dernier->suivant=e; dernier=e; } } template<class S> void Liste<S>:: inserer(const Iterateur<S> &pos, const S& s){ Element<S> *e=new Element<S>(s); if(pos.position == premier){ premier->precedent=e; e->precedent=NULL; e->suivant=premier; premier=e; } else if(pos.position==NULL){ dernier->suivant=e; e->suivant=NULL; e->precedent=dernier; dernier=e; } else{ e->precedent =pos.position->precedent; e->suivant=pos.position; (pos.position)->precedent->suivant=e; (pos.position)->precedent=e; } } template<class S> void Liste<S>::supprimer(Iterateur<S>& pos){ if(pos.position==NULL){ cout<<"\n la liste est vide ! ou la position indiquée est NULL :\n rien à supprimer\n"<<endl; } else if(pos.position == premier){ Iterateur<S> tmp=pos; ++pos; premier->suivant->precedent=NULL; premier=premier->suivant; delete tmp.position; } else if(pos.position == dernier){ Iterateur<S> tmp=pos; ++pos; dernier->precedent->suivant=NULL; dernier=dernier->precedent; delete tmp.position; } else{ Iterateur<S> tmp=pos; ++pos; (tmp.position)->precedent->suivant=(tmp.position)->suivant; (tmp.position)->suivant->precedent=(tmp.position)->precedent; delete tmp.position; } } "test_list.cc" (main) #include <string> #include <list> #include "liste.h" #include <iostream> using namespace std; int main(){ Liste<int> personnel; Iterateur<int> pos; // ajouter 4 elements personnel.ajouter(12); personnel.ajouter(17); personnel.ajouter(15); personnel.ajouter(27); // test du constructeur par recopie Liste<int> toto(personnel); // inserer un element a la quatrieme position pos = toto.debut(); pos++; pos++; pos++; toto.inserer(pos, 77); // supprimer l'element a la deuxieme position pos = toto.debut(); pos++; toto.supprimer(pos); // afficher tous les elements for (pos = toto.debut(); pos!=(toto.fin()); ++pos) cout << *pos << endl; //test de l'operateur d'affectation Liste<int> toto2; toto2=toto; cout << "\n\ndeuxième affichage :"<< endl; for (pos = toto2.debut(); pos!=(toto2.fin()); ++pos) cout << *pos << endl; // personnel.~Liste(); // toto.~Liste(); // toto2.~Liste(); return 0; } voila le tout compiler grace a ce makefile simplissime : liste: liste.o test_list.o g++ -o liste liste.cc test_list.cc liste.h liste.o: liste.cc liste.h g++ -o liste.o -c liste.cc liste.h test_list.o: test_list.cc liste.cc liste.h g++ -o test_list.o -c test_list.cc liste.h ^^ bonne lecture |
et voila le résultat de la compilation :
g++ -c liste.cc g++ -c test_list.cc g++ -o liste liste.o test_list.o test_list.o(.text+0x1b): In function `main': : undefined reference to `Liste<int>::Liste[in-charge]()' test_list.o(.text+0x26): In function `main': : undefined reference to `Iterateur<int>::Iterateur[in-charge]()' test_list.o(.text+0x3f): In function `main': : undefined reference to `Liste<int>::ajouter(int const&)' test_list.o(.text+0x58): In function `main': : undefined reference to `Liste<int>::ajouter(int const&)' test_list.o(.text+0x71): In function `main': : undefined reference to `Liste<int>::ajouter(int const&)' test_list.o(.text+0x8a): In function `main': : undefined reference to `Liste<int>::ajouter(int const&)' test_list.o(.text+0x9c): In function `main': : undefined reference to `Liste<int>::Liste[in-charge](Liste<int> const&)' test_list.o(.text+0xae): In function `main': : undefined reference to `Liste<int>::debut() const' test_list.o(.text+0xd0): In function `main': : undefined reference to `Iterateur<int>::operator++(int)' test_list.o(.text+0xe3): In function `main': : undefined reference to `Iterateur<int>::operator++(int)' test_list.o(.text+0xf6): In function `main': : undefined reference to `Iterateur<int>::operator++(int)' test_list.o(.text+0x116): In function `main': : undefined reference to `Liste<int>::inserer(Iterateur<int> const&, int const&)' test_list.o(.text+0x128): In function `main': : undefined reference to `Liste<int>::debut() const' test_list.o(.text+0x14a): In function `main': : undefined reference to `Iterateur<int>::operator++(int)' test_list.o(.text+0x15c): In function `main': : undefined reference to `Liste<int>::supprimer(Iterateur<int>&)' test_list.o(.text+0x16e): In function `main': : undefined reference to `Liste<int>::debut() const' test_list.o(.text+0x18f): In function `main': : undefined reference to `Liste<int>::fin() const' test_list.o(.text+0x1a4): In function `main': : undefined reference to `Iterateur<int>::operator!=(Iterateur<int> const&) const' test_list.o(.text+0x1b5): In function `main': : undefined reference to `Iterateur<int>::operator*() const' test_list.o(.text+0x1e2): In function `main': : undefined reference to `Iterateur<int>::operator++()' test_list.o(.text+0x1f2): In function `main': : undefined reference to `Liste<int>::Liste[in-charge]()' test_list.o(.text+0x207): In function `main': : undefined reference to `Liste<int>::operator=(Liste<int> const&)' test_list.o(.text+0x243): In function `main': : undefined reference to `Liste<int>::debut() const' test_list.o(.text+0x270): In function `main': : undefined reference to `Liste<int>::fin() const' test_list.o(.text+0x288): In function `main': : undefined reference to `Iterateur<int>::operator!=(Iterateur<int> const&) const' test_list.o(.text+0x299): In function `main': : undefined reference to `Iterateur<int>::operator*() const' test_list.o(.text+0x2c6): In function `main': : undefined reference to `Iterateur<int>::operator++()' test_list.o(.text+0x2d6): In function `main': : undefined reference to `Liste<int>::~Liste [in-charge]()' test_list.o(.text+0x2e1): In function `main': : undefined reference to `Liste<int>::~Liste [in-charge]()' test_list.o(.text+0x2ec): In function `main': : undefined reference to `Liste<int>::~Liste [in-charge]()' test_list.o(.text+0x312): In function `main': : undefined reference to `Liste<int>::~Liste [in-charge]()' test_list.o(.text+0x331): In function `main': : undefined reference to `Liste<int>::~Liste [in-charge]()' test_list.o(.text+0x350): more undefined references to `Liste<int>::~Liste [in-charge]()' follow collect2: ld a retourné 1 code d'état d'exécution make: *** [liste] Erreur 1 |
Salut.
Je n'ai pas tout regarder en détail, mais il me semble voir l'erreur. Les templates ne sont pas des fonctions habituel. Essai de tout mettre dans le .h, ça devrai fonctionner. à prendre sous réserve : lorsque tu compile un template, la vrai fonction typer (avec int ou double à la place de T) n'est creer que quand elle est appeler dans le code, donc dans ton liste.cc tu ne fait apel à aucune fonction, donc elle n'est pas creer. et test.c ne voi pas la definition du constructeur qui est dans liste.cc Salutation ! Char Snipeur |
en effet, test_list ne voyai pas la definition du constructeur ...
j'ai essayer de mettre le code comme tu disai dans le .h mai il y avai alors interaction entre les différente instance de Element et il y avai des erreur due a une definition multiple etc ... j'ai essayer de metre include"liste.cc" dans le .h ce qui a donné le meme resultat, et au final la soluytion ça a été de rajouter #include"liste.cc" dans le test_list.cc ;) et hop ça roule ! merci bybye! |
En fait, ce qu'il faut faire c mettre liste.cc dans le .h et supprimer liste.cc
Salutation !
Char Snipeur |
Bonjour,
Désolé de faire remonter ce topic mais je suis tombé dessus par une recherche Google car j'ai EXACTEMENT le même problème. J'ai crée un class Liste pour faire une liste chainée, temporairement une liste de caractère. J'ai voulu l'étendre à une liste d'éléments quelconque avec les templates. Seulement, je me suis rendu compte que une fois toutes les modifications faites, il y a une erreur à la compile: "undefined references to `Liste<int>::Liste(void)`" Dans le main.cpp, j'inclus juste le fichier liste.h Et je me suis rendu compte que si j'inclus la source, liste.cpp, alors l'erreur disparait et la liste fonctionne correctement. Plus haut dans ce topic, il est dit de tout mettre dans le .h (ce qui devrait fonctionner) mais cependant je voudrais savoir s'il n'est pas possible de conserver la séparation entre implémentation et spécification, en clair toujours séparer le .h et le code source. Merci de votre aide ! |
Salut.
Non, c'est impossible. Les template doivent être entièrement dans un .h ! un template est valable pour n'importe quel type, intégré ou non. C'est à dire que tu peux utilisé les template avec des class. Comment un compilateur pourrai deviner quel class sera utilisé avnt même qu'elle soit créer ? C'est pour cela qu'il est impossible de compiler des templates en dehors d'un lien avec un fichier cpp qui appel ses fonctions Salutation ! Char Snipeur
|
je crois que tu peux quand meme separer le truc c'est d'inclure le .ccp a la fin du .hh. Ca revient a tout mettre dans le header mais c'est plus propre ainsi.
ekeyno |
Résultats pour [c++ template]undefine reference to ...
Résultats pour [c++ template]undefine reference to ...
Résultats pour [c++ template]undefine reference to ...
Résultats pour [c++ template]undefine reference to ...
Résultats pour [c++ template]undefine reference to ...
Résultats pour [c++ template]undefine reference to ...
Résultats pour [c++ template]undefine reference to ...