我有一个新项目,正在为双向链接列表中的条目创建一个类。我使用的是面向对象的样式,对此我经验有限。构造函数和函数在单独的文件中定义。
头文件:
#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
语句中的取消引用。
这解决了该错误,并且还没有找到更多错误,但是却给您带来了另一个问题,如果删除了复制构造函数,您将遇到另一个问题。现在,您有两个LISTEntry
和prev
和next
相同。这可能会导致列表不稳定。使用副本,您可以将废话从原件 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想知道如果您总是创建一个新节点,您打算链接一个现有节点吗?这将使插入,删除和排序变得非常困难。