C ++ шаблоны - LinkedList

ОТРЕДАКТИРУЙТЕ - Ответил ниже, пропустил угловые фигурные скобки. Спасибо все.

Я пытался написать элементарный отдельно связанный список, который я могу использовать в других программах. Я хочу, чтобы это было в состоянии работать со встроенным, и пользователь определил типы, подразумевая, что это должен быть templated.

Из-за этого моего узла должен также быть templated, поскольку я не знаю информации, которую он собирается хранить. Я написал класс узла следующим образом -

template <class T> class Node
{
    T data; //the object information
    Node* next; //pointer to the next node element

public:
    //Methods omitted for brevity
};

Мой связанный класс списка осуществлен в отдельном классе и должен иллюстрировать примерами узел, добавляя новые узлы до конца списка. Я осуществил это следующим образом -

#include <iostream>
#include "Node.h"
using namespace std;

template <class T> class CustomLinkedList
{
    Node<T> *head, *tail;

public:

    CustomLinkedList()
    {
        head = NULL;
        tail = NULL;
    }

    ~CustomLinkedList()
    {

    }

    //Method adds info to the end of the list
    void add(T info)
    {
        if(head == NULL) //if our list is currently empty
        {
            head = new Node<T>; //Create new node of type T
            head->setData(info);
            tail = head;
        }
        else //if not empty add to the end and move the tail
        {
            Node* temp = new Node<T>;
            temp->setData(info);
            temp->setNextNull();
            tail->setNext(temp);
            tail = tail->getNext();
        }
    }

    //print method omitted
};

Я настроил класс водителя/теста следующим образом -

#include "CustomLinkedList.h"
using namespace std;

int main()
{
    CustomLinkedList<int> firstList;

    firstList.add(32);
    firstList.printlist();
    //Pause the program until input is received
    int i;
    cin >> i;

    return 0;
}

Я получаю ошибку после компиляции однако - ошибка C2955: 'Узел': использование шаблона класса требует списка аргументов шаблона - который указывает мне на следующую строку кода в моем добавлять метод -

Node* temp = new Node<T>;

Я не понимаю, почему у этого нет информации о типе, так как он был передан к связанному списку, когда было создано в моем классе водителя. Что я должен делать, чтобы передать информацию о типе к Узлу?

Я должен создать частную структуру узла вместо отдельного класса и объединить методы обоих классов в одном файле? Я не уверен, что это преодолело бы проблему, но я думаю, что она могла бы. У меня были бы отдельные классы, если это возможно, все же.

Спасибо, Эндрю.

11
задан Drew_StackID 16 January 2010 в 23:46
поделиться

6 ответов

Может быть также попытаться попробовать

Node<T>* temp = new Node<T>;

также, чтобы получить советы о том, как разработать список, вы можете, конечно, можно посмотреть на STD :: Список, хотя иногда это может быть немного пугающим.

9
ответ дан 3 December 2019 в 04:52
поделиться

Существует большая разница в обработке истории командной строки между консолью Windows и терминалами Unix. В Windows это делается консолью, в то время как в Unix за это отвечают приложения. Я ничего не знаю о Перле, но тебе нужно использовать что-то вроде библиотеки readline. Это выглядит полезно: http://perldoc.perl.org/functions/readline.html

-121--4435372-

Я считаю, что ответ «не определен» спецификацией языка.

Смещение поиска основано на начале координат, так что вы можете искать файл больше long max. вы просто не можете искать из начала файла. Кроме того, объект файла не должен поддерживать поиск для чтения. Дополнительная информация содержится в документе FileStream.Seek Documentation

Возможно, кто-то знает лучше, но я не верю, что определен максимальный размер файла. Вы будете ограничены тем, что вы делаете с данными, считанными из файловой системы (например, нехватка памяти для ее хранения и т.д.)

-121--4667840-

Эта строка должна иметь значение

Node<T>* temp = new Node<T>;

То же самое для указателя next в классе Node.

1
ответ дан 3 December 2019 в 04:52
поделиться
121 --- 1998244-

Вам нужно:

Node<T> *temp = new Node<T>;

может стоить Typedef NodeType = узел в CustomLinkedList класс для предотвращения Эта проблема снова обрезается.

0
ответ дан 3 December 2019 в 04:52
поделиться

Как уже говорилось, решение -

Node<T>* temp = new Node<T>;

... потому что Узел сам по себе не является типом, Узел является.

1
ответ дан 3 December 2019 в 04:52
поделиться

, и вам нужно указать параметр шаблона для Node * Temp в PrintList.

0
ответ дан 3 December 2019 в 04:52
поделиться

В то время как ответы уже были предоставлены, я думаю, я добавлю свое зерно соли.

При проектировании классанов класса, это хорошая идея не повторять шаблон аргументов почти везде, на всякий случай, если вы хотите (однажды) изменить определенную деталь. В общем, это делается с помощью Typedefs.

template <class T>
class Node
{
public:
  // bunch of types
  typedef T value_type;
  typedef T& reference_type;
  typedef T const& const_reference_type;
  typedef T* pointer_type;
  typedef T const* const_pointer_type;

  // From now on, T should never appear
private:
  value_type m_value;
  Node* m_next;
};


template <class T>
class List
{
  // private, no need to expose implementation
  typedef Node<T> node_type;

  // From now on, T should never appear
  typedef node_type* node_pointer;

public:
  typedef typename node_type::value_type value_type;
  typedef typename node_type::reference_type reference_type;
  typedef typename node_type::const_reference_type const_reference_type;
  // ...

  void add(value_type info);

private:
  node_pointer m_head, m_tail;
};

Также лучше определить методы вне объявления класса, затрудняет прочесть интерфейс.

template <class T>
void List<T>::add(value_type info)
{
  if(head == NULL) //if our list is currently empty
  {
    head = new node_type;
    head->setData(info);
    tail = head;
  }
  else //if not empty add to the end and move the tail
  {
    Node* temp = new node_type;
    temp->setData(info);
    temp->setNextNull();
    tail->setNext(temp);
    tail = tail->getNext();
  }
}

Теперь пару замечаний:

  • Было бы более удобным для пользователя, если список :: Add возвращал итератор на новые добавленные объекты, как Вставка Методы делают в STL (и вы можете переименовать его тоже)
  • в реализации списка :: add вы назначаете память на TEMP , затем выполните кучу Операции, если какие-либо броски, вы утечли память
  • Setnextnull Setnextnull , не должны быть необходимы: Конструктор Узел должен инициализировать все элементы данных для значений, которые включены m_next

Итак, вот пересмотренная версия:

template <class T>
Node<T>::Node(value_type info): m_value(info), m_next(NULL) {}

template <class T>
typename List<T>::iterator insert(value_type info)
{
  if (m_head == NULL)
  {
    m_head = new node_type(info);
    m_tail = m_head;
    return iterator(m_tail);
  }
  else
  {
    m_tail.setNext(new node_type(info));
    node_pointer temp = m_tail;
    m_tail = temp.getNext();
    return iterator(temp);
  }
}

Обратите внимание, как простой факт использования правильного конструктора улучшает нашу безопасность исключения: если когда-либо что-нибудь бросит во время конструктора, New требуется не Выделите любую память, поэтому ничего не утечка, и мы еще не выполняли никакой операции. Наш Список :: Вставка теперь устойчиво.

Окончательный вопрос:

Обычно Вставка Методы вставки с одним связанным списками в начале, потому что это проще:

template <class T>
typename List<T>::iterator insert(value_type info)
{
  m_head = new node_type(info, m_head); // if this throws, m_head is left unmodified
  return iterator(m_head);
}

Вы уверены, что хотите пойти с вставкой в ​​конце? Или вы сделали это таким образом из-за Push_Back на традиционные векторы и списки?

12
ответ дан 3 December 2019 в 04:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: