Построение шаблона ошибки C ++

У меня проблема со сборкой моей программы. Я ищу ошибку с некоторого часа, и я не понимаю, в чем проблема.

Вот мой код:
ListeBase.h

    #ifndef LISTEBASE_H
#define LISTEBASE_H
#include "Timing.h"#include "Professeur.h"#include "Cours.h"#include "Local.h"#include "Groupe.h"template<class T> struct Cellule
{
T Valeur ;
Cellule<T> *psuivant ;
};

template <class T> class ListeBase
{
protected:
Cellule<T> *Ptete;
public:
ListeBase();
ListeBase(ListeBase<T>& LB);
virtual ~ListeBase();
Cellule<T> * getTete(void)const;
void setTete(Cellule<T> *Te);
int estVide(void)const;
int getNombreElements(void)const;
void Affiche(void);
virtual T* insere(const T& val)=0;
};

#endif

ListeBase.cpp

#include "../Header/ListeBase.h"#include <iostream>
using namespace std;
template <class T> ListeBase<T>::ListeBase()
{
cout << "Methode Constructeur ListeBase" << endl;
Ptete=0;
}
template <class T> ListeBase<T>::ListeBase(ListeBase<T>& LB)
{
setTete(LB.getTete());
}
template <class T> ListeBase<T>::~ListeBase()
{
Cellule<T> *Temp,*Test;

cout << "Methode destructeur ListeBase" << endl;
do
{
Temp=Ptete->psuivant;
delete Ptete; // IL FALLAIT UN OPERATOR= DE TIMING SINON IL Y AVAIT DEUX ELEMENT A LA MEME ADRESSE
Ptete=Temp;
}while(Ptete!=0);
cout << "Test" << endl;
}
template <class T> Cellule<T>* ListeBase<T>::getTete(void)const
{
cout << "Methode getTete" << endl;
return Ptete;
}
template <class T> void ListeBase<T>::setTete(Cellule<T> *Te)
{
cout << "Methode SetTete" << endl;
if(Te!=0)
this->Ptete=Te;
}
template <class T> int ListeBase<T>::estVide(void)const
{
if(getTete()==0)
return 0;
return 1;
}
template <class T> int ListeBase<T>::getNombreElements(void)const
{
Cellule<T> *Temp;
int i=0;

Temp=getTete();

while((*Temp).psuivant!=0)
{
i++;
Temp=(*Temp).psuivant;
}

return i;
}
template <class T> void ListeBase<T>::Affiche(void)
{
Cellule<T> *Temp;
int i=0;

cout << "Methode affiche" << endl;
Temp=getTete();
while(Temp!=0)
{
cout << Temp->Valeur << endl;
Temp=Temp->psuivant;
}
cout << "FIN AFFICHE" << endl;
}
template class ListeBase<int>;
template class ListeBase<Timing>;
template class ListeBase<Professeur>;
template class ListeBase<Groupe>;
template class ListeBase<Local>;
template class ListeBase<Cours>;

Liste.cpp

  #include "../Header/Liste.h"
template <class T> Liste<T>::Liste():ListeBase<T>()
{
cout << "Methode COnstructeur Liste" << endl;
}
template <class T> Liste<T>::Liste(const Liste<T>& L)
{
cout << "Methode COnstructeur Liste COPIE" << endl;
this->setTete(L.getTete());
}
template <class T> Liste<T>::~Liste()
{
cout << "Methode Destructeur Liste" << endl;
}
template <class T> T* Liste<T>::insere(const T& Val)
{
Cellule<T>* Temp;
Temp=new Cellule<T>;
cout << "Methode insere Liste" << endl;
Temp->psuivant=this->getTete();
Temp->Valeur=Val;
this->setTete(Temp);

return &this->getTete()->Valeur;
}

template class Liste<int>;
template class Liste<Timing>;
template class Liste<Professeur>;
template class Liste<Groupe>;
template class Liste<Local>;
template class Liste<Cours>;

Liste.h

    #ifndef LISTE_H
#define LISTE_H

#include "ListeBase.h"#include "Groupe.h"#include "Professeur.h"#include "Local.h"#include "Cours.h"
template <class T>
class Liste : public ListeBase<T>
{
public:
Liste();
Liste(const Liste<T>& L);
~Liste();
T* insere(const T& Val);
};

#endif

Cours.h

#ifndef COURS_H
#define COURS_H

#include "Liste.h"#include "string.h"#include "Event.h"#include "Professeur.h"
class Cours:public Event
{
friend ostream& operator<<(ostream& s,const Cours& C);

private:
char* Prof;
Liste<int> Groupes;
public:
Cours();
Cours(const int Code,const char* Intitule,const char* Lieu,const Timing& timing, Professeur& P);
Cours(const int Code,const char* Intitule,const char* Lieu,const Timing& timing, Professeur& P,Liste<int>&G);
Cours(const Cours& C);

Cours& operator=(const Cours& C);

int operator>(const Cours& C)const;//
int operator<(const Cours& C)const;// DEMANDE DEXPLICATION SUR LA VALEUR DU RETURN
int operator==(const Cours& C)const;//
int compH(const Cours& C)const;

Liste<int> getGroupes(void)const;
void setGroupes(const Liste<int> G);
char* getProf(void)const;
void setProf(const char* P);

};#endif

Это сообщение об ошибке:

In file included from Cpp/../Header/Cours.h:4:0,
from Cpp/../Header/ListeBase.h:6,
from Cpp/ListeBase.cpp:1:

Cpp/../Header/Liste.h:11:31: error: expected template-name before ‘<’ token
class Liste : public ListeBase<T>
^
Cpp/../Header/Liste.h:11:31: error: expected ‘{’ before ‘<’ token

Cpp/../Header/Liste.h:11:31: error: expected unqualified-id before ‘<’ token

In file included from Cpp/../Header/ListeBase.h:6:0,
from Cpp/ListeBase.cpp:1:

Cpp/../Header/Cours.h:15:14: error: field ‘Groupes’ has incomplete type
Liste<int> Groupes;

Большое спасибо за помощь

0

Решение

У вас есть циркуляр, включающий:

ListeBase.cpp -> ListeBase.h -> Cours.h -> Liste.h -> ListeBase.h

При включении Liste.h в этот момент класс ListeBase неизвестен. Циркулярное включение останавливается с помощью #ifndef LISTEBASE_H

Измените свой дизайн (я не уверен, что базовый шаблон должен включать некоторые аппликативные заголовки)

Также, как упоминалось ранее, реализация шаблона должна быть известна во время компиляции, поэтому реализация должна быть в заголовке, а не в исходном файле.


РЕДАКТИРОВАТЬ

Распространенный способ использования шаблона:

ListeBase.h, который определяет и реализует ТОЛЬКО ListeBase

Liste.h, который определяет и реализует Liste, который наследуется от BaseListe

Каждый заголовок или источник, которым требуется использование шаблона, должен включать Liste.h и использовать его напрямую, без объявления чего-либо в cpp до

С нашим дизайном мне кажется сложно использовать CPP для определения шаблона. в соответствии с циркулярным

Я рекомендую вам использовать этот способ. Это верный путь.

Примечание: вы можете увидеть ключевое слово «extern» для шаблона (только C ++ 11)


EDIT2

В любой ситуации важно минимизировать зависимости, поэтому в любое время, когда включаете заголовок, подумайте над этим: «Действительно ли моя реализация / заголовок должна знать это?» и «Какой файл какой использовать?»

В последнем вопросе, если ответ связан с зависимостью от круговорота, существует ошибка проектирования

0

Другие решения

Других решений пока нет …