[c++ template]undefine reference to ...
Résolu/Fermé
guian
Messages postés
27
Date d'inscription
mardi 24 octobre 2006
Statut
Membre
Dernière intervention
24 mai 2007
-
31 oct. 2006 à 14:21
FredericHam - 8 juil. 2013 à 16:09
FredericHam - 8 juil. 2013 à 16:09
A voir également:
- [c++ template]undefine reference to ...
- Reference pto - Accueil - Box & Connexion Internet
- Qwerty to azerty - Guide
- Press esc in 1 seconds to skip startup.nsh any other key to continue ✓ - Forum Windows 10
- Welcome to nginx! ✓ - Forum Applis & Sites
- 1 to ✓ - Forum Windows
16 réponses
Char Snipeur
Messages postés
9813
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
1 298
15 juin 2009 à 08:16
15 juin 2009 à 08:16
Si je comprends bien, tu n'a que deux fichiers, le .h avec la déclaration des structures, et le .cpp contenant leur définition ainsi que le main. Si c'est bien ça, il est normal que ça fonctionne. Mais ça ne fonctionnera pas dans tout les cas. Tu sort du cadre du problème.
Essai de faire une bibliothèque juste histoire de bien te prouver que ce n'est pas possible.
Dans ton cas, ça fonctionne car tu mets le définition des fonction dans la même unité de compilation que son appel.
Essai de faire une bibliothèque juste histoire de bien te prouver que ce n'est pas possible.
Dans ton cas, ça fonctionne car tu mets le définition des fonction dans la même unité de compilation que son appel.
Char Snipeur
Messages postés
9813
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
1 298
19 mars 2007 à 08:49
19 mars 2007 à 08:49
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
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
Char Snipeur
Messages postés
9813
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
1 298
6 nov. 2006 à 08:40
6 nov. 2006 à 08:40
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
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
guian
Messages postés
27
Date d'inscription
mardi 24 octobre 2006
Statut
Membre
Dernière intervention
24 mai 2007
1
8 nov. 2006 à 10:21
8 nov. 2006 à 10:21
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!
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!
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
Char Snipeur
Messages postés
9813
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
1 298
31 oct. 2006 à 16:51
31 oct. 2006 à 16:51
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?
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?
guian
Messages postés
27
Date d'inscription
mardi 24 octobre 2006
Statut
Membre
Dernière intervention
24 mai 2007
1
2 nov. 2006 à 13:24
2 nov. 2006 à 13:24
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
(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
guian
Messages postés
27
Date d'inscription
mardi 24 octobre 2006
Statut
Membre
Dernière intervention
24 mai 2007
1
6 nov. 2006 à 08:13
6 nov. 2006 à 08:13
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
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
Char Snipeur
Messages postés
9813
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
1 298
8 nov. 2006 à 11:02
8 nov. 2006 à 11:02
En fait, ce qu'il faut faire c mettre liste.cc dans le .h et supprimer liste.cc
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 !
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 !
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
ekeyno
Char Snipeur
Messages postés
9813
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
1 298
12 juin 2009 à 15:16
12 juin 2009 à 15:16
ça, c'est ton avis.
faire un .cpp qui s'inclus, je trouve ça sale.
faire un .cpp qui s'inclus, je trouve ça sale.
Ta ta ta, on peut separer declaration et definition pour les templates :
.h
template<typename T, typename S> class FF
{
T t;
S s;
T &GetValT();
S &GetValS();
};
.cpp
template<typename T, typename S> T &FF<typename T, typename S>::GetValT()
{
return t;
}
template<typename T, typename S> S &FF<typename T, typename S>::GetValS()
{
return s;
}
.h
template<typename T, typename S> class FF
{
T t;
S s;
T &GetValT();
S &GetValS();
};
.cpp
template<typename T, typename S> T &FF<typename T, typename S>::GetValT()
{
return t;
}
template<typename T, typename S> S &FF<typename T, typename S>::GetValS()
{
return s;
}
Char Snipeur
Messages postés
9813
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
1 298
12 juin 2009 à 15:17
12 juin 2009 à 15:17
As tu testé ton programme ?
Je te garanti que ça ne fonctionne pas.
Je te garanti que ça ne fonctionne pas.
La syntaxe est bonne bien que
template<typename T, typename S> T &FF<typename T, typename S>::GetValT()
puisse s ecrire plus simplement
template<typename T, typename S> T &FF<T, S>::GetValT()
Il suffit d ajouter un contructeur a FF afin d initialiser ses valeurs et rendre celui ci et ses methodes publiques ce qui donne :
template<typename T, typename S> class FF
{
T t;
S s;
public:
FF(T t_, S s_) : t(t_), s(s_){}
T &GetValT();
S &GetValS();
};
Sinon oui ca marche :
// main
FF<int, char> f(5, 'a');
int var1 = f.GetValT(); // var1 = 5
char var2 = f.GetValS(); // var2 = 'a'
template<typename T, typename S> T &FF<typename T, typename S>::GetValT()
puisse s ecrire plus simplement
template<typename T, typename S> T &FF<T, S>::GetValT()
Il suffit d ajouter un contructeur a FF afin d initialiser ses valeurs et rendre celui ci et ses methodes publiques ce qui donne :
template<typename T, typename S> class FF
{
T t;
S s;
public:
FF(T t_, S s_) : t(t_), s(s_){}
T &GetValT();
S &GetValS();
};
Sinon oui ca marche :
// main
FF<int, char> f(5, 'a');
int var1 = f.GetValT(); // var1 = 5
char var2 = f.GetValS(); // var2 = 'a'
Char Snipeur
Messages postés
9813
Date d'inscription
vendredi 23 avril 2004
Statut
Contributeur
Dernière intervention
3 octobre 2023
1 298
12 juin 2009 à 16:27
12 juin 2009 à 16:27
donne voir le code source entier.
lol mais t es un sacre blagueur toi !
Recapitulatif pour ceux qui ont du mal :
.h
template<typename T, typename S> class FF
{
T t;
S s;
public:
FF(T t_, S s_) : t(t_), s(s_){}
T &GetValT();
S &GetValS();
};
.cpp
#include "MonFichierHCiDessus.h"
template<typename T, typename S> T &FF<T, S>::GetValT()
{
return t;
}
template<typename T, typename S> S &FF<T, S>::GetValS()
{
return s;
}
int main ()
{
FF<int, char> f(5, 'a');
int var1 = f.GetValT(); // var1 = 5
char var2 = f.GetValS(); // var2 = 'a'
}
Recapitulatif pour ceux qui ont du mal :
.h
template<typename T, typename S> class FF
{
T t;
S s;
public:
FF(T t_, S s_) : t(t_), s(s_){}
T &GetValT();
S &GetValS();
};
.cpp
#include "MonFichierHCiDessus.h"
template<typename T, typename S> T &FF<T, S>::GetValT()
{
return t;
}
template<typename T, typename S> S &FF<T, S>::GetValS()
{
return s;
}
int main ()
{
FF<int, char> f(5, 'a');
int var1 = f.GetValT(); // var1 = 5
char var2 = f.GetValS(); // var2 = 'a'
}
21 déc. 2009 à 18:29
Pour séparer un .h et .cpp pour les templates, dans ton .h tu doit spécifié les différents types que tu va utilisé pour instancié ta template (en générale, quand on écrit un programme, on le sait). Et c'est tout ))
Pour plus d'info, va chercher sur google, avant de dire des bétises))
22 déc. 2009 à 08:26
Si tu prend par exemple le conteneur std::vector, tu ne peut pas connaître tout ces types possible à l'avance, et pour cause la personne qui l'a développé n'est pas celle qui l'utilise !
Et tu remarquera que le code de ce conteneur (a minima pour la partie dépendante du type) est entièrement dans un .h, il n'y a rien de compiler.