2010-01-03 12 views
12

He intentado implementar mi propia clase de lista vinculada para fines didácticos.Error del compilador al declarar una clase de amigo de plantilla dentro de una clase de plantilla

Especifiqué la clase "Lista" como amigo dentro de la declaración del iterador, pero parece que no compila.

Estas son las interfaces de las 3 clases que he usado:

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

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

Y este es el programa de prueba que he estado tratando de correr:

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

Cuando intento compilar, el compilador me da los siguientes errores :

Iterator.h: 26: error: 'Lista' no es una plantilla

Iterator.h: En instanciación de 'iterador':

trial.cpp: 18: instancia de aquí

Iterator.h: 12: error: argumento de plantilla requerida para la 'Lista struct '

List.cc: En función miembro 'Iterator Lista :: createStartIterator() const [con T = int]':

trial.cpp: 18: instancia de aquí

Iterator.h: 14: error: 'Iterator :: iterador (Nodo *) [con T = int]' es privada

Lista .cc: 120: error: en este contexto

Parece que no está reconociendo la declaración del amigo. ¿Dónde me equivoqué?

+0

No defina su propia macro nula (o NULL, o nada relacionado). En el caso de inicializar miembros de datos, '0' funciona bien. –

+0

Sé que es feo, solo fue temporal. Pero estaba bastante seguro de que C++ no permitía la conversión implícita. –

+0

Los lanzamientos nunca son implícitos, pero las conversiones sí lo son. (Dos caras de la misma moneda, podría decir, y "conversión" también se usa para nombrar métodos que convierten un valor entre otros usos, pero ese es un tipo diferente de conversión.) Lo que necesita para inicializar un puntero es otro puntero de tipo adecuado, o una constante de puntero nulo; '0' es una constante de puntero nulo perfectamente fina (' NULL' también, si lo prefiere). –

Respuesta

15

intento de añadir una declaración hacia adelante

template <class T> class List; 

al comienzo de Iterator.h - que podría ser lo que necesita para permitir la declaración friend dentro de la clase Iterator para trabajar.

+0

¡Gracias! Esto funcionó para mí. – sgowd

5

El problema es que la Lista no se ha declarado correctamente en Iterator.h. En su lugar, anide la clase Iterator dentro de List (automágicamente convirtiéndola en una plantilla), lo que probablemente quiera hacer de todos modos (para usar List :: Iterator en lugar de cambiarle el nombre a ListIterator o IteratorForList, ya que tendría más de un iterador en un espacio de nombres).

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