Создание класса входа для связанного списка - PullRequest
1 голос
/ 29 февраля 2020

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

Заголовочный файл:

#ifndef LISTENTRY_H_JDP
#define LISTENTRY_H_JDP

#include "DATAClass.h"
#include <iostream>

using namespace std;

typedef DATAClass l;
typedef class LISTEntry *listptr;

class LISTEntry
{
  DATAClass data;
  listptr prev;
  listptr next;

public:
  LISTEntry();
  LISTEntry(DATAClass l);
  LISTEntry(LISTEntry &le);
  ~LISTEntry();

  LISTEntry getNext();
  void setNext();

  LISTEntry getPrev();
  void setPrev();

  DATAClass getData();
  void setData(DATAClass d);
};

#endif // LISTENTRY_H_INCLUDED

Файл реализации:

#include "LISTEntry.h"

LISTEntry::LISTEntry()
{
    data = data;
    prev = NULL;
    next = NULL;
}

LISTEntry::LISTEntry(DATAClass l)   //take an item of type l and convert it into a LISTEntry
{
    data = l;
    prev = NULL;
    next = NULL;
}

LISTEntry::LISTEntry(LISTEntry &le)
{
    data = le.getData();
    prev = le.getPrev();
    next = le.getNext();
}

LISTEntry::~LISTEntry()
{
}

LISTEntry LISTEntry::getNext()
{
    return *next;
}

void LISTEntry::setNext()
{
    next = new LISTEntry;
}

LISTEntry LISTEntry::getPrev()
{
    return *prev;
}

void LISTEntry::setPrev()
{
    prev = new LISTEntry;
}

DATAClass LISTEntry::getData()
{
    return data;
}

void LISTEntry::setData(DATAClass d)
{
    data = d;
}

Проблема в моем конструкторе копирования, LISTEntry ( LISTEntry & le). До сих пор я получаю сообщение об ошибке:

не может преобразовать 'LISTEntry' в 'listptr {aka LISTEntry *}'

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

1 Ответ

1 голос
/ 29 февраля 2020

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

Если l написано плохо (нарушает Правила трех или пяти ), нет необходимости в конструкторе копирования или деструкторе в LISTEntry. LISTEntry не имеет собственных специальных ресурсов и должен быть в состоянии соблюдать правило нуля. Если l не работает, исправьте l, не навязывайте его fl aws другим классам.

Но это не то, что вы хотите сделать по нескольким причинам.

Основная проблема, вызывающая сообщение об ошибке: prev = le.getPrev(); пытается присвоить копию предыдущего узла LISTEntry источника новому указателю LISTEntry на предыдущий узел.

prev нужен адрес LISTEntry, а не LISTEntry.

В связанном списке LISTEntry LISTEntry::getNext() и LISTEntry LISTEntry::getPrev() почти наверняка не должны возвращать копию узла, на который указывает. Вы хотите вернуть указатель. Если вы этого не сделаете, то обнаружите, что перебор связанного списка - это приключение. Вы будете работать, возможно, изменяя копии узлов, а не оригиналы. Хаос.

Измените их на LISTEntry * LISTEntry::getNext() и удалите разыменование в операторе return.

Это устраняет ошибку, и еще несколько, которые вы еще не нашли, но оставляет у вас другая проблема, и та же, что и у вас, если вы удалите конструктор копирования. Теперь у вас есть два LISTEntry с одинаковыми prev и next. Это может привести к нестабильному списку. С копией вы можете выбросить дерьмо из списка оригинала. Не круто. Быть осторожен. На самом деле вам лучше НЕ копировать ссылки и не создавать конструктор копирования:

LISTEntry::LISTEntry(const LISTEntry &le) // make everything const until proven otherwise
{
    data = le.data; // this is a member function so it can access private variables
                    // no need for the accessor function
    prev = nullptr;
    next = nullptr;
}

Вам также нужен / нужен оператор присваивания

LISTEntry & operator=(const LISTEntry &le)
{
    if (this != &le)
    {
        data = le.data; 
        prev = nullptr;
        next = nullptr;
    }
}

Вы также должны обсудить

void LISTEntry::setNext()
{
    next = new LISTEntry;
}

с вашей резиновой уткой . Даки хочет знать, планируете ли вы связать существующий узел, если вы всегда создаете новый? Это действительно затруднит вставку, удаление и сортировку.

...