2011-03-01 1 views
1

J'ai une structure de noeud et une classe de pile. Quand je mets la définition de « vide poussée (données T) » en dehors de la définition de la classe je reçois:Fonctions membres d'une classe basée sur un modèle, prenant un type de modèle en tant qu'argument

error: 'template<class T> class Stack' used without template parameters 

Mais quand je l'ai mis dans la définition de la classe il fonctionne très bien.
Voici le code:

template <class T> 
struct Node 
{ 
    Node(T data, Node <T> * address) : Data(data), p_Next(address) {} 
    T Data; 
    Node <T> * p_Next; 
}; 

template <class T> 
class Stack 
{ 
public: 

    Stack() : size(0) {} 
    void Push(T data); 
    T Pop(); 

private: 
    int size; 
    Node <T> * p_first; 
    Node <T> * p_last; 
}; 

La mise en œuvre pour Push (données T) est:

void Stack::Push(T data) 
{ 
    Node <T> * newNode; 

    if(size==0) 
     newNode = new Node <T> (data, NULL); 
    else 
     newNode = new Node <T> (data, p_last); 

    size++; 
    p_last = newNode; 
} 

Edit: Les solutions élaborées sauf que maintenant je reçois une erreur qui relie chaque fois que je tente d'appeler la les fonctions.

Stack<int>::Pop", referenced from 
_main in main.o 
symbol(s) not found. 

à moins que les définitions sont en Stack.h au lieu de Stack.cpp

Répondre

4

Vous devez utiliser le nouveau template <class T> (puis de les utiliser à nouveau T comme paramètre de modèle pour la classe):

template <class T> 
void Stack<T>::Push(T data) 
{ 
    Node <T> * newNode; 

    if(size==0) 
     newNode = new Node <T> (data, NULL); 
    else 
     newNode = new Node <T> (data, p_last); 

    size++; 
    p_last = newNode; 
} 
+0

@ user4: savez-vous pourquoi je pourrais avoir l'erreur de liaison? –

+0

C'est un effet secondaire regrettable de la façon dont les modèles sont implémentés en C++. Étant donné que les paramètres doivent être connus au moment de la compilation, vous ne pouvez pas compiler le code du modèle, puis lui lier le code suivant, car le compilateur doit connaître les instanciations spécifiques du fichier suivant à créer pour le premier fichier. au fichier suivant, il est trop tard. Voir http://www.parashift.com/c++-faq-lite/templates.html#faq-35.13 pour une explication complète et des solutions de contournement. – user470379

+0

@ user4: serait-il considéré comme une solution appropriée de simplement mettre les définitions de fonction dans Stack.h avec la définition de classe? –

4

Vous devez ajouter une déclaration de modèle avant que les fonctions membres lorsqu'elles sont définies en dehors de la classe ...

template <class T> 
void Stack<T>::Push(T data) 
{ 
    Node <T> * newNode; 

    if(size==0) 
     newNode = new Node <T> (data, NULL); 
    else 
     newNode = new Node <T> (data, p_last); 

    size++; 
    p_last = newNode; 
} 

(Au moins, il devrait être similaire à ceci.)

+0

Cela a fonctionné, sauf qu'il ne me laisse pas appeler les fonctions si les définitions sont dans Stack.cpp, alors que cela fonctionne si la définition est dans Stack.h. Je reçois l'erreur de liaison: "Stack :: Pop", référencé par _main dans le (s) main.o symbole (s) non trouvé. Mais je peux appeler des fonctions non-membres depuis Stack.cpp. –

+0

Les implémentations réelles des modèles C++ requièrent que le code d'implémentation figure dans l'en-tête. Un exemple de ceci peut être trouvé dans la bibliothèque standard de C++. Si vous regardez les en-têtes de bibliothèque standard fournis avec votre compilateur, vous remarquerez que les modèles de classe ont l'implémentation complète de la classe, pas seulement les déclarations de méthode. - La ligne du bas: mettre la définition de la méthode dans le fichier d'en-tête aussi; l'éditeur de liens et le compilateur doivent gérer le reste. – dappawit

2

C'est parce que lorsque la définition est dans la définition de la classe, il connaît le paramètre du modèle. Si vous voulez mettre la définition à l'extérieur, vous devez indiquer explicitement au compilateur que T est un paramètre de modèle ...

template <class T> 
void Stack<T>::Push(T data) {/* code */} 
+0

savez-vous pourquoi je pourrais avoir l'erreur de liaison? –

Questions connexes