我有一个新项目,我正在为双向链接列表中的条目创建一个类。我使用的是面向对象的样式,对此我经验有限。构造函数和函数在单独的文件中定义。
头文件:
#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函数。我希望他们链接到列表中相同类型的新条目。我想我在构造函数中实现指针时遇到麻烦。有人可以帮忙吗?
您可以通过删除复制构造函数来解决问题,但这掩盖了导致错误的问题。
除非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
。这可能会导致列表不稳定。使用副本,您可以将废话从原件清单中剔除。不酷小心。实际上,最好不要复制链接并创建复制构造函数:
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想知道,如果您总是创建一个新节点,您打算链接一个现有节点吗?这将使插入,删除和排序变得非常困难。
您可以通过删除复制构造函数来解决问题,但这掩盖了导致错误的问题。
除非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
。这可能会导致列表不稳定。使用副本,您可以将废话从原件清单中剔除。不酷小心。实际上,最好不要复制链接并创建复制构造函数:
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想知道,如果您总是创建一个新节点,您打算链接一个现有节点吗?这将使插入,删除和排序变得非常困难。