С++ двусвязный список с нулевой объектной моделью

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

Примечание. Это школьное задание. Пожалуйста, не публикуйте решение без объяснения причин. Я хочу узнать и понять, что здесь происходит.

Редактировать: После устранения проблемы с отображением у меня появилась другая: при вызове getHead() или getTail() со списком, который пуст или имеет узлы, он продолжает хотеть использовать self() из класса узлов , а не класс nullNode (в случае пустого списка) или класс elementNode (в случае списка с узлами). Я застрял на том, как это исправить.

Если я распечатаю адреса container.getNext() и container (для пустого списка), оба адреса будут одинаковыми, поэтому не следует добавлять ->self() в конец вызова метода self() из класса nullNode?

class node {
public:

    node(){/* Do nothing */}

    node(int e){ element = e; }

    int getData(){ return element; }

    void setData(int e){ element = e; }

    friend class list;
protected:
    node* getNext(){ return next; }

    void setNext(node* n){ next = n; }

    node* getPrev() { return prev; }

    void setPrev(node* n){ prev = n; }

    node* self();

private:

    int element;
    node* next;
    node* prev;
};

class nullNode : public node{
public:
    nullNode(){/* Do nothing */}

    int getData(){ return NULL; }

    void setData(int e){ /* Do Nothing */ }

    node* getNext(){ return head; }

    void setNext(node* n){ head = n; }

    node* getPrev() { return tail; }

    void setPrev(node* n){ tail = n; }

    node* self(){ return NULL; }
private:
    node* head;
    node* tail;
};

class elementNode : public node{
public:
    elementNode(){/* Do nothing */}

    elementNode(int element){
        setData(element);
}

    int getData(){ return node::getData(); }

    void setData(int e){ node::setData(e); }

    node* getNext(){ return node::getNext(); }

    void setNext(node* n){ node::setNext(n); }

    node* getPrev() { return node::getPrev(); }

    void setPrev(node* n){ node::setPrev(n); }

    node* self(){ return this; }
};

class list{
public:

    list();

    node* getHead(){ return (container.getNext())->self(); }

    node* getTail(){ return (container.getPrev())->self(); }

    node* addHeadNode(int e);

    void removeNode(node* n);

    void insertBefore(node* n, int e);

    void insertAfter(node* n, int e);

    void displayNode(node *n);

private:

    nullNode container;
};

list::list()
{
    container.setNext(&container);
    container.setPrev(&container);
}

node* list::addHeadNode(int e)
{
    node* foo = new elementNode(e);

    foo->setPrev(&container);
    foo->setNext(container.getNext());
    container.getNext()->setPrev(foo);
    container.setNext(foo);
    return foo;
}

void list::displayNode(node* n)
{
    cout << "Node Data: " << n->getData() << endl;
}
int main()
{
    list myList;
    node* myNode;
    myNode = myList.addHeadNode(5);
    myList.displayNode(myNode);

    return 0;
}

person Derek    schedule 15.07.2012    source источник
comment
Вы должны выполнять свой код построчно в отладчике, чтобы проверять значения переменных по мере выполнения вашей программы. В качестве альтернативы вы можете добавить множество операторов печати для достижения аналогичного эффекта. Например, если вы проверяете foo->getData() внутри функции addHeadNode(), правильно ли это?   -  person Oliver Charlesworth    schedule 15.07.2012


Ответы (3)


elementNode(int element)
{
    node e;
    e.setData(element);
}

Что делает этот код? Вы создаете узел e, но затем он выбрасывается и не добавляется ни в один список.

person Jonathan Wood    schedule 15.07.2012

Проблема скрывается в

elementNode(int element){
    node e;
    e.setData(element);
}

Что здесь происходит? Сначала вы создаете экземпляр класса node, а затем вызываете его функцию-член setData. Конечно, e изменяется со значением element, но в следующий момент и e, и element исчезают из существования, потому что область, в которой они были инициализированы, прекратила свое существование (завершается }), в то время как информация в element не была сохраняется где угодно.

Однако, если вы замените приведенный выше код на

elementNode(int element){
    setData(element);
}

он вызывает унаследованную функцию-член setData, значение element сохраняется, и программа выводит 5, как и ожидалось.

person Desmond Hume    schedule 15.07.2012
comment
Да, это имеет смысл. Спасибо! У меня другая проблема, которую я не понимаю. Исходный пост отредактирован. - person Derek; 15.07.2012

Ваш конструктор elementNode пытается инициализировать свою часть node:

elementNode(int element){
  node e;
  e.setData(element);
}

На самом деле вы просто создаете несвязанный узел, а затем отбрасываете его.

Что вы хотите, так это вызвать конструктор вашего суперкласса, что можно сделать в списке инициализации конструктора подкласса:

elementNode(int element) : node(element) {
}
person Mud    schedule 15.07.2012