2010-01-03 5 views
12

J'ai essayé d'implémenter ma propre classe de liste chaînée à des fins didactiques.Erreur de compilation lors de la déclaration d'une classe d'ami modèle dans une classe modèle

J'ai spécifié la classe "List" comme ami dans la déclaration Iterator, mais il ne semble pas compiler.

Ce sont les interfaces des 3 classes que j'ai utilisé:

Node.h:

#define null (Node<T> *) 0 

template <class T> 
class Node { 
public: 
    T content; 
    Node<T>* next; 
    Node<T>* prev; 

    Node (const T& _content) : 
     content(_content), 
     next(null), 
     prev(null) 
    {} 
}; 

Iterator.h:

#include "Node.h" 

template <class T> 
class Iterator { 
private: 
    Node<T>* current; 

    Iterator (Node<T> *); 

public: 
    bool isDone() const; 

    bool hasNext() const; 
    bool hasPrevious() const; 
    void stepForward(); 
    void stepBackwards(); 

    T& currentElement() const; 

    friend class List<T>; 
}; 

Liste. h

#include <stdexcept> 
#include "Iterator.h" 

template <class T> 
class List { 
private: 
    Node<T>* head; 
    Node<T>* tail; 
    unsigned int items; 

public: 
    List(); 

    List (const List<T>&); 
    List& operator = (const List<T>&); 

    ~List(); 

    bool isEmpty() const { 
     return items == 0; 
    } 
    unsigned int length() const { 
     return items; 
    } 
    void clear(); 

    void add (const T&); 
    T remove (const T&) throw (std::length_error&, std::invalid_argument&); 

    Iterator<T> createStartIterator() const throw (std::length_error&); 
    Iterator<T> createEndIterator() const throw (std::length_error&); 
}; 

C'est le programme de test que j'ai essayé de courir:

trial.cpp

using namespace std; 
#include <iostream> 
#include "List/List.cc" 

int main() 
{ 
List<int> myList; 

for (int i = 1; i <= 10; i++) { 
    myList.add(i); 
} 

for (Iterator<int> it = myList.createStartIterator(); !it.isDone(); it.stepForward()) { 
    cout << it.currentElement() << endl; 
} 

return 0; 
} 

Lorsque je tente de le compiler, le compilateur me donne les erreurs suivantes :

Iterator.h: 26: erreur: 'List' est pas un modèle

Iterator.h: Dans instanciation 'itérateur':

trial.cpp: 18: instancié d'ici

Iterator.h: 12: Erreur: argument modèle requis pour « Liste struct '

List.cc: en fonction membre 'Iterator :: Liste createStartIterator() const [avec T = int]':

trial.cpp: 18: instancié d'ici

Iterator.h: 14: Erreur: 'Iterator :: iterator (Noeud *) [avec T = int]' est privé

Liste .cc: 120: erreur: dans ce contexte

On dirait qu'il ne reconnaît pas la déclaration d'ami. Où est-ce que je me suis trompé?

+0

Ne définissez pas votre propre macro null (ou NULL, ou n'importe quoi d'autre). Dans le cas de l'initialisation des membres de données, '0' fonctionne très bien. –

+0

Je sais que c'est moche, c'était seulement temporaire. Mais j'étais tout à fait sûr que C++ n'autorisait pas le casting implicite. –

+0

Les lancers ne sont jamais implicites, mais les conversions le sont. (Deux côtés de la même pièce, vous pourriez dire, et "conversion" est également utilisé pour nommer des méthodes qui convertissent une valeur parmi d'autres utilisations, mais c'est un type différent de conversion.) Ce que vous devez initialiser un pointeur est un autre pointeur type approprié ou une constante de pointeur nulle; '0' est une constante de pointeur null parfaitement fine (' NULL' est aussi, si vous préférez). –

Répondre

15

essayer d'ajouter une déclaration avant

template <class T> class List; 

au début de Iterator.h - qui pourrait être ce dont vous avez besoin pour permettre la déclaration friend dans la classe Iterator pour travailler.

+0

Merci! Cela a fonctionné pour moi. – sgowd

5

Le problème est que List n'a pas été déclaré correctement dans Iterator.h. Au lieu de cela, imbriquez la classe Iterator dans List (ce qui en fait automatiquement un modèle), ce que vous voudrez probablement faire de toute façon (pour utiliser List :: Iterator au lieu de le renommer ListIterator ou IteratorForList, car vous auriez plus d'un Iterator dans un espace de noms).

template<class T> 
struct List { 
    //... 
    struct Node {/*...*/}; 
    struct Iterator { 
    // ... 
    private: 
    Iterator(Node*); 
    friend class List; // still required 
    }; 
    //... 
}; 
Questions connexes