ОТРЕДАКТИРУЙТЕ - Ответил ниже, пропустил угловые фигурные скобки. Спасибо все.
Я пытался написать элементарный отдельно связанный список, который я могу использовать в других программах. Я хочу, чтобы это было в состоянии работать со встроенным, и пользователь определил типы, подразумевая, что это должен быть 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>;
Я не понимаю, почему у этого нет информации о типе, так как он был передан к связанному списку, когда было создано в моем классе водителя. Что я должен делать, чтобы передать информацию о типе к Узлу?
Я должен создать частную структуру узла вместо отдельного класса и объединить методы обоих классов в одном файле? Я не уверен, что это преодолело бы проблему, но я думаю, что она могла бы. У меня были бы отдельные классы, если это возможно, все же.
Спасибо, Эндрю.
Может быть также попытаться попробовать
Node<T>* temp = new Node<T>;
также, чтобы получить советы о том, как разработать список, вы можете, конечно, можно посмотреть на STD :: Список, хотя иногда это может быть немного пугающим.
Существует большая разница в обработке истории командной строки между консолью 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.
Вам нужно:
Node<T> *temp = new Node<T>;
может стоить Typedef NodeType = узел
в CustomLinkedList
класс для предотвращения Эта проблема снова обрезается.
Как уже говорилось, решение -
Node<T>* temp = new Node<T>;
... потому что Узел
сам по себе не является типом, Узел
является.
, и вам нужно указать параметр шаблона для Node * Temp в PrintList.
В то время как ответы уже были предоставлены, я думаю, я добавлю свое зерно соли.
При проектировании классанов класса, это хорошая идея не повторять шаблон аргументов почти везде, на всякий случай, если вы хотите (однажды) изменить определенную деталь. В общем, это делается с помощью 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
, не должны быть необходимы: Конструктор Узел
должен инициализировать все элементы данных для значений, которые включены 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
на традиционные векторы и списки?