У меня есть одна семестра (собственный двойной связанный список), и наш учитель хочет этого определения класса DoubleList:
template <typename T> //just part of all methods
class DoubleList {
public:
DoubleList(void); //We HAVE TO follow this definitions
void AddFirst(const T &); //const!
T &AccessActual(void);
T RemoveFirst(void);
}
Мой вопрос: как я могу определить узел? AddFirst
есть аргумент const, а другие методы - нет. Данные должны быть установлены в конструкторе, а затем они не могут быть изменены. Является ли эта задача настолько ограниченной или есть другие способы выполнить задачу?
Вот мой фактический Node
:
template <class U>
class Node{
Node<U> * next;
Node<U> * previous;
const U * data;
public:
Node(const U *data){ //
next = NULL;
previous = NULL;
this->data = data;
}
void SetNext(Node<U> *next) {
this->next = next;
}
Node<U> *GetNext(){ return next; }
void SetPrevious(Node<U> *previous) {
this->previous = previous;
}
Node<U> *GetPrevious(){ return previous; }
const U *GetData() { return data; }
};
В контейнерах обычно лучше иметь копию данных, поэтому изменяйте const U * data;
к U data;
Конструктор узла был бы проще использовать, если бы у него был этот сигнатурный Node(const U& data)
. Нет указателей.
Также необходимо будет изменить GetData. Верните ссылку. U& GetData()
.
Сохранять адреса элементов данных опасно. Если пользователь списков хочет эту функциональность, он может использовать список, в котором хранятся указатели (например, U = int *)
Класс вашего узла кажется прекрасным, хотя я бы продолжал использовать шаблонный аргумент T вместо U, сейчас он запутан.
Ваш метод AddFirst() должен просто создать новый узел и назначить правильный следующий указатель на новый узел и правильный указатель на "старый" первый узел и настроить фактический объект? к чему это относится?
Ваш интерфейс узлов отличается от того, который возвращает ссылку вместо указателя. Мне довольно странно, что AccessActual всегда может возвращать объект, а когда список пуст, это может быть nullptr??
пример реализации:
void AddFirst(const T &)
{
Node<T>* newNode = new Node<T>(T);
Node<T>* current = &AccessActual(); // how can there be an actual when the list can be empty or is that impossible?
{
while( current.GetPrev() != nullptr )
{
current = *current.GetPrev();
}
current.SetPrev(newnode);
newnode->SetNext(current);
}
}
(void)
в объявлениях вашего метода.