2013-03-30 3 views
1

Я не могу склонить голову вокруг концепции использования вложенных классов в C++.C++ - Где определить функции вложенного класса?

Я пытаюсь создать итератор для связанного списка. Я объявил его как вложенный класс в личном контексте LinkedList.h

Но где определить функции класса Iterator? Прямо сейчас, я пытаюсь сделать это в нижней части файла вместе со всеми функциями LinkedList. Но независимо от того, как я пытаюсь скрутить и вращать определения области, я не могу заставить его работать. Должен ли я делать это по-другому?

Итератор Iterator класс

class Iterator { 

    private: 

     LinkedList<T>* l; 
     Node<T>* node; 

    public: 

     Iterator(LinkedList<T> *ll, Node<T> *n);   
     T get(); 
     int hasNext(); 
     void moveNext(); 

    }; 

Четыре функции определений

template <typename T> 
typename LinkedList<T>::Iterator<T>::Iterator(LinkedList<T> *ll, Node<T> *n) { 
    l = ll; 
    node = n; 
} 

template <typename T> 
T LinkedList<T>::Iterator<T>::get() { 
    return node->getData(); 
} 

template <typename T> 
int LinkedList<T>::Iterator<T>::hasNext() { 
    return node->getNext(); 
} 

template <typename T> 
void LinkedList<T>::Iterator<T>::moveNext() { 
    node = node->getNext(); 
} 

Ошибки я получаю являются:

"Использование неопределенного типа: LinkedList :: Итератор"

"Синтаксическая ошибка: неожиданный тип LinkedList"

«Синтаксическая ошибка: отсутствует»; до '{' '

и многие другие.

Я так очень, очень потерян.

редактировать:

Файл LinkedList.h в полном объеме:

#ifndef LINKEDLIST_H 
#define LINKEDLIST_H 
#include "Node.h" 
#include "List.h" 
#include <iostream> 

template <typename T> 
class LinkedList : public List { 

private: 

    int n; 
    Node<T> *first; 
    Node<T> *last; 

    template <typename T> 
    class Iterator { 

    private: 

     LinkedList<T>* l; 
     Node<T>* node; 

    public: 

     Iterator(LinkedList<T> *ll, Node<T> *n);   
     T get(); 
     int hasNext(); 
     void moveNext(); 

    }; 

public: 

    LinkedList(); 
    LinkedList(const LinkedList & ll); 
    ~LinkedList(); 
    int size(); 
    void clear(); 
    void addFirst(T data); 
    void addLast(T data); 
    T removeFirst(); 
    T removeLast(); 
    T getFirst(); 
    T getLast(); 
    Node<T>* getFirstNode() const; 
    void addAt(int pos, T data); 
    T removeAt(int pos); 
    T getAt(int pos); 
    LinkedList& operator=(const LinkedList<T> &right); 
    T operator[](int i); 
    LinkedList& operator+(const LinkedList<T> &right); 
    LinkedList& operator+=(const LinkedList<T> &right); 
    friend std::ostream& operator<<(std::ostream &os, const LinkedList<T> & ll); 
    typename LinkedList<T>::Iterator<T> getIterator(); 
    void mergeSort(); 
}; 

template <typename T> 
LinkedList<T>::LinkedList() { 
     this->n = 0; 
     this->first = 0; 
     this->last = 0; 
    } 

template <typename T> 
LinkedList<T>::LinkedList(const LinkedList & ll) { 
    this-> n = 0; 
    this-> first = 0; 
    this-> last = 0; 

    Node *temp = ll.first; 

    while(temp) { 
     addLast(temp->getData()); 
     temp = temp->getNext(); 
    } 

} 

template <typename T> 
void LinkedList<T>::addFirst(T data) { 
    Node<T> *p = new Node<T>(data, first); 
    first = p; 
    if(!n) 
     last = p; 
    n++; 
} 

template <typename T> 
void LinkedList<T>::addLast(T data) { 
    Node<T> *p = new Node<T>(data, 0); 
    if(!n) 
     first = last = p; 
    else { 
     last->next = p; 
     last = p; 
    } 
    n++; 
} 

template <typename T> 
T LinkedList<T>::removeFirst() { 
    T a = 0; 
    if(!n) 
     throw "Can't retrieve element from empty list!"; 
    a = first->getData(); 
    Node<T> *p = first->next; 
    delete first; 
    first = p; 
    n--; 
    return a; 
} 

template <typename T> 
T LinkedList<T>::removeLast() { 
    T a = 0; 
    if(!n) 
     throw "Can't retrieve element from empty list!"; 
    if(n == 1) { 
     a = last->getData(); 
     delete first; 
     first = last = 0; 
    } 
    else { 
     a = last->getData(); 
     Node<T> *p = first; 
     while(p->next->next != 0) 
      p = p->next; 
     delete p->next; 
     p->next = 0; 
     last = p; 
    } 
    n--; 
    return a; 
} 

template <typename T> 
T LinkedList<T>::getFirst() { 
    if(n < 1) 
     throw "Can't retrieve element from empty list!"; 
    return first->getData(); 
} 

template <typename T> 
T LinkedList<T>::getLast() { 
    if(n < 1) 
     throw "Can't retrieve element from empty list!"; 
    return last->getData(); 
} 

template <typename T> 
Node<T>* LinkedList<T>::getFirstNode() const { 
    return first; 
} 

template <typename T> 
int LinkedList<T>::size() { 
    return n; 
} 

template <typename T> 
T LinkedList<T>::getAt(int pos) { 
    if(pos >= n) 
     throw "Element index out of bounds!";  
    Node<T> *temp = first; 
    while(pos > 0) { 
     temp = temp->next; 
     pos--; 
    } 
    return temp->getData();  
} 

template <typename T> 
void LinkedList<T>::clear() { 
    Node<T> *current = first; 
    while(current) { 
     Node<T> *next = current->next; 
     delete current; 
     if(next) 
      current = next; 
     else 
      current = 0; 
    } 
} 

template <typename T> 
void LinkedList<T>::addAt(int pos, T data) { 
    if(pos >= n) 
     throw "Element index out of bounds!";  
    if(pos == 0) 
     addFirst(data); 
    else { 
     Node<T> *temp = first; 
     while(pos > 1) { 
      temp = temp->next; 
      pos--; 
     } 
     Node<T> *p = new Node<T>(data, temp->next); 
     temp-> next = p; 
     n++; 
    } 
} 

template <typename T> 
T LinkedList<T>::removeAt(int pos) { 
    if(pos >= n) 
     throw "Element index out of bounds!";  
    if(pos == 0) 
     return removeFirst(); 
    if(pos == n - 1) 
     return removeLast(); 
    else { 
     Node<T> *p = first; 
     while(pos > 1) { 
      p = p->next; 
      pos--; 
     } 
     T a = p->next->getData(); 
     Node<T> *temp = p->next; 
     p->next = p->next->next; 
     delete temp; 
     n--; 
     return a; 
    }  
} 

template <typename T> 
LinkedList<T>::~LinkedList() { 
    clear(); 
} 

template <typename T> 
LinkedList<T>& LinkedList<T>::operator=(const LinkedList<T> &right) { 
    if(this != &right) { 

     n = 0; 
     first = 0; 
     last = 0; 

     Node<T> *temp = right.first; 
     while(temp) { 
      addLast(temp->getData()); 
      temp = temp->getNext(); 
     }   
    } 
    return *this; 
} 

template <typename T> 
T LinkedList<T>::operator[](int i) { 
    return getAt(i); 
} 

template <typename T> 
LinkedList<T>& LinkedList<T>::operator+(const LinkedList<T> &right) { 
    Node<T> *temp = right.first; 
    while(temp) { 
     addLast(temp->getData()); 
     temp = temp->getNext(); 
    } 
    return *this; 
} 

template <typename T> 
LinkedList<T>& LinkedList<T>::operator+=(const LinkedList<T> &right) { 
    Node<T> *temp = right.first; 
    while(temp) { 
     addLast(temp->getData()); 
     temp = temp->getNext(); 
    } 
    return *this; 
} 

template <typename T> 
std::ostream& operator<<(std::ostream &os, const LinkedList<T> &ll) { 
    Node<T> *temp = ll.getFirstNode(); 
    while(temp) { 
     os<<temp->getData()<<std::endl; 
     temp = temp->getNext(); 
    } 
    return os; 
} 

template <typename T> 
typename LinkedList<T>::Iterator<T>::Iterator(LinkedList<T> *ll, Node<T> *n) { 
    l = ll; 
    node = n; 
} 

template <typename T> 
T LinkedList<T>::Iterator<T>::get() { 
    return node->getData(); 
} 

template <typename T> 
int LinkedList<T>::Iterator<T>::hasNext() { 
    return node->getNext(); 
} 

template <typename T> 
void LinkedList<T>::Iterator<T>::moveNext() { 
    node = node->getNext(); 
} 

template <typename T> 
typename LinkedList<T>::Iterator<T> LinkedList<T>::getIterator() { 
    return new Iterator<T>(*this, *first); 
} 

#endif 
+1

'Iterator' не является вложенным классом в вашем фрагменте кода. –

+0

Когда вы говорите внизу, вы имеете в виду внизу файла заголовка? – 2013-03-30 12:54:06

+0

Разве это не вложенный класс, если ключевое слово «класс» (и его кодовый блок) входит в какое-либо другое объявление класса?Если я должен определить функции Итератора во всей полноте в блоке классов, как мне это сделать? –

ответ

2

вам необходимо либо использовать шаблон TypeName из LinkedList (что имеет смысл). Это означает, что вам не требуется отдельное имя шаблона для класса Iterator.

template <typename T> 
class Iterator { 

должен быть только

class Iterator { 

И тогда члены будут определены как

template <typename T> 
T LinkedList<T>::Iterator::get() { 

ИЛИ если вы действительно нужен другой TypeName для итератора. Тогда, по крайней мере, вы должны изменить имя от T, потому что оно будет теневым для LinkedList. Что-то вроде

template <typename V> 
class Iterator { 
    ... 
    V get(); 
    ... 

И декларациях memeber примет форму

template <typename T> 
template <typename V> 
V LinkedList<T>::Iterator<V>::get() { 
+0

Большое спасибо! Я думаю, что сейчас работает. Как связанный вопрос: Как я могу использовать функцию getIterator() в моей основной? Я не могу назначить его для типа Iterator, так как это частный, вложенный тип, верно? –

+0

Я думаю, что у вас нет итератора-члена в вашем связанном классе. В нем есть определение класса. Но он не объявил в этом объект такого типа. Возможно, вам понадобится что-то вроде 'Iterator iter' как член LinkedList – 2013-03-30 13:38:34

+0

И затем инициализируйте его, передав ему связанный с владельцем список. Итак, экземпляры LinkedList и Iterator знают друг друга. Но обратите внимание на порядок инициализации. Итериальный memeber должен быть инициализирован после того, как все материалы, связанные с списком, будут выполнены. например, копирование .... – 2013-03-30 13:41:25

1

Я думаю, что это будет делать:

template <typename T> 
LinkedList<T>::Iterator::Iterator(LinkedList<T> *ll, Node<T> *n) { 
    l = ll; 
    node = n; 
} 

template <typename T> 
T LinkedList<T>::Iterator::get() { 
    return node->getData(); 
} 

template <typename T> 
int LinkedList<T>::Iterator::hasNext() { 
    return node->getNext(); 
} 

template <typename T> 
void LinkedList<T>::Iterator::moveNext() 
{ 
    node = node->getNext(); 
} 
+0

Спасибо. Я до сих пор получаю ошибки, но путь меньше :) я получаю: «Использование шаблона класса требует списка аргументов шаблона» для конструктора «не в состоянии соответствовать определению существующей декларации» для конструктора «'получить 'не является функцией " –

+0

Как и в случае с кем-то другим, удаление шаблона для класса Iterator (и исправление раздражающей маленькой опечатки с помощью« get ») решило это. Спасибо вам, ребята! –