我有一个新项目,正在为双向链接列表中的条目创建一个类。我使用的是面向对象的样式,对此我经验有限。构造函数和函数在单独的文件中定义。

头文件:

#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)。到目前为止,我收到错误消息:



我也不确定get和set函数。我希望他们链接到列表中相同类型的新条目。我想我在构造函数中实现指针时遇到麻烦。有人可以帮忙吗?

最佳答案

您可以通过删除复制构造函数来解决问题,但这可以隐藏导致错误的问题。

除非l写得不好(违反the Rules of Three or Five),否则不需要在LISTEntry中使用复制构造函数或析构函数。 LISTEntry本身没有特殊的资源,应该能够遵守零规则。如果l损坏,请修复l,不要在其他类上造成缺陷。

但这不是您要执行的操作,原因有两个。

导致错误消息的根本问题是prev = le.getPrev();试图将源LISTEntry的先前节点的副本分配给新LISTEntry的指向先前节点的指针。
prev需要LISTEntry的地址,而不是LISTEntry

在链接列表中,LISTEntry LISTEntry::getNext()LISTEntry LISTEntry::getPrev()几乎肯定不会返回所指向节点的副本。您要返回指针。否则,您会发现遍历链表是一次冒险。您将操作(可能会修改)节点副本而不是原始副本。困惑随之而来。

将它们更改为LISTEntry * LISTEntry::getNext()并删除return语句中的取消引用。

这解决了该错误,并且还没有找到更多错误,但是却给您带来了另一个问题,如果删除了复制构造函数,您将遇到另一个问题。现在,您有两个LISTEntryprevnext相同。这可能会导致列表不稳定。使用副本,您可以将废话从原件 list 中剔除。不酷小心。实际上,最好不要复制链接并创建复制构造函数:

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;
}

your rubber duck。 Ducky想知道如果您总是创建一个新节点,您打算链接一个现有节点吗?这将使插入,删除和排序变得非常困难。

10-07 12:30