2010-01-03 6 views
12

Ich habe versucht, meine eigene Linked-List-Klasse für didaktische Zwecke zu implementieren.Compiler-Fehler beim Deklarieren von Template-Freundes-Klasse innerhalb einer Template-Klasse

Ich habe die "List" -Klasse als Freund in der Iterator-Deklaration angegeben, aber es scheint nicht zu kompilieren.

Dies sind die Schnittstellen der drei Klassen die ich verwendet habe:

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&); 
}; 

Und das ist das Prüfprogramm ich versucht habe zu laufen:

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; 
} 

Wenn ich versuche, es zu kompilieren, gibt der Compiler mir die folgenden Fehler :

Iterator.h: 26: Fehler: 'List' ist keine Vorlage

Iterator.h

: In Instantiierung 'Iterator':

trial.cpp: 18: instanziiert von hier

Iterator.h: 12: Fehler: Template-Argument erforderlich für ‚struct Liste '

List.cc: In Memberfunktion 'Iterator List :: createStartIterator() const [mit T = int]':

trial.cpp: 18: von hier instanziiert

Iterator.h: 14: Fehler: 'Iterator :: Iterator (Node *) [mit T = int]'

Liste ist privat .cc: 120: Fehler: in diesem Zusammenhang

Scheint wie es die Freunddeklaration nicht erkennt. Wo bin ich falsch gelaufen?

+0

Definieren Sie kein eigenes Null- (oder NULL- oder ähnliches) Makro. Im Falle der Initialisierung von Datenelementen funktioniert "0" gut. –

+0

Ich weiß, es ist hässlich, es war nur vorübergehend. Aber ich war mir ziemlich sicher, dass C++ das implizite Casting nicht erlaubte. –

+0

Casts sind niemals implizit, aber Conversions sind. (Zwei Seiten der gleichen Münze, könnte man sagen, und "Konvertierung" wird auch verwendet, um Methoden zu benennen, die einen Wert unter anderen Verwendungen konvertieren, aber das ist eine andere Art von Konvertierung.) Was Sie einen Zeiger initialisieren müssen, ist ein anderer Zeiger von geeigneter Typ oder eine Nullzeigerkonstante; '0' ist eine vollkommen feine Nullzeigerkonstante (' NULL' ist auch, wenn Sie bevorzugen). –

Antwort

15

versuchen, eine Vorwärts-Deklaration

template <class T> class List; 

zu Beginn der Iterator.h Zugabe - das sein könnte, was Sie die friend Erklärung innerhalb der Iterator Klasse ermöglichen, arbeiten müssen.

+0

Vielen Dank! Das hat für mich funktioniert. – sgowd

5

Das Problem ist Liste wurde nicht ordnungsgemäß in Iterator.h deklariert. Verschachteln Sie stattdessen die Iterator-Klasse innerhalb von List (was automatisch zu einer Vorlage wird), was Sie wahrscheinlich trotzdem tun möchten (um List :: Iterator anstelle von ListIterator oder IteratorForList zu verwenden, da Sie mehr als einen Iterator haben würden) in einem Namensraum).

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