我需要帮助重载“+”运算符,以便将两个双向链接列表相加。由于得到“不匹配operator = ...”错误,我无法编译我的程序。我已经重载了'='运算符,但很难打印添加到std输出的结果。我也重载了<<运营商。一直试图弄清楚什么是错误的几个小时没有成功。任何提示如何解决这个问题和/或解决方案都是非常受欢迎的。这是我的OOP课程的作业。 提前谢谢!
编辑:代码背后的基本思想是复制集合。重载运算符'+'应该作为联合使用,'*'作为交集。我很难将联合正确打印到std输出。 '+ ='似乎工作正常。 '<<'效果也不错,但只有在打印单个列表时才会有效。
编辑: 编译器产生的错误(g ++,代码:: blocks的输出,我已经删除了编译器注释):
llist3.cpp|149|error: no match for ‘operator=’ (operand types are ‘LList’ and ‘LList’)|
llist3.cpp|106|note: no known conversion for argument 1 from ‘LList’ to ‘LList&’|
llist3.cpp|151|error: no match for ‘operator=’ (operand types are ‘LList’ and ‘LList’)|
llist3.cpp|106|note: no known conversion for argument 1 from ‘LList’ to ‘LList&’|
llist3.cpp|152|error: no match for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream<char>}’ and ‘LList’)|
#include<iostream>
using namespace std;
class LList {
public:
struct Node {
int elem;
Node* succ;
Node* prev;
Node() : succ(0), prev(0), elem(0) {}
};
LList();
LList(LList& list);
~LList();
Node* next();
Node* begin() { curr = head; }
int getElem() { return curr->elem; }
void addElem(int elem);
LList operator+(LList& set);
LList operator+(int elem);
LList& operator+=(LList& set);
LList& operator+=(int elem);
LList& operator=(LList& list);
friend ostream& operator<<(ostream& os, LList& obj);
private:
Node* curr;
Node* head;
Node* tail;
int size;
void pushFront(Node* n);
void pushInside(Node* n);
void pushBack(Node* n);
};
LList::LList() : head(0), tail(0), size(0), curr(0) {}
LList::LList(LList& list) : size(0), curr(0), head(0), tail(0) {
list.curr = list.head;
while(list.curr) {
addElem(list.getElem());
list.next();
}
}
LList::Node* LList::next() {
if (curr)
return (curr = curr->succ);
else
return 0;
}
void LList::addElem(int elem) {
Node* n = new Node;
n->elem = elem;
if (curr) {
if (curr == head && elem < curr->elem) {
pushFront(n);
}
else if (elem > curr->elem) {
curr = curr->succ;
addElem(elem);
}
else if (elem < curr->elem && elem > (curr->prev)->elem) {
pushInside(n);
}
else if (elem < curr->elem) {
curr = curr->prev;
addElem(elem);
}
} else {
pushBack(n);
}
}
void LList::pushFront(Node* n) {
head = n;
n->succ = curr;
curr->prev = n;
n->prev = 0;
curr = n;
size++;
}
void LList::pushInside(Node* n) {
(curr->prev)->succ = n;
n->succ = curr;
n->prev = curr->prev;
curr->prev = n;
size++;
}
void LList::pushBack(Node* n) {
if (!head) {
head = n;
} else {
tail->succ = n;
n->prev = tail;
}
tail = n;
curr = n;
size++;
}
LList::~LList() {
for (curr = head; curr;) {
Node* temp = curr->succ;
delete curr;
curr = temp;
}
}
LList& LList::operator=(LList& list) {
list.begin();
if (this != &list) {
for (curr = head; curr;) {
Node* temp = curr->succ;
delete curr;
curr = temp;
}
while (list.curr) {
addElem(list.getElem());
list.next();
}
}
return *this;
}
ostream& operator<<(ostream& os, LList& list) {
LList::Node* p = list.head;
os << "{ ";
while(p) {
os << p->elem << (p->succ ? ", " : "");
p = p->succ;
}
os << " }" << endl;
return os;
}
LList LList::operator+(LList& set) {
LList temp = *this;
temp += set;
return temp;
}
LList LList::operator+(int elem) {
*this += elem;
return *this;
}
int main() {
LList setA;
setA.addElem(1234);
setA.addElem(1435);
setA.addElem(1100);
LList setB;
setB.addElem(1234);
setB.addElem(1435);
setB.addElem(5100);
setB = setA + 1234; // 1st error here
LList setD;
setD = setA + setB; //2nd
cout << setA + setB << endl; //3rd
}
答案 0 :(得分:2)
您的代码中存在一个明显的错误:
Node* begin() { curr = head; }
此代码调用未定义的行为,因为您没有返回值。它应该是这样的:
Node* begin() { curr = head; return curr; }
此外,您应该在不更改LList
参数的函数中通过const引用传递LList
:
例如:
LList::LList(LList& list);
LList& operator=(LList& list);
friend ostream& operator<<(ostream& os, LList& obj);
应该是:
LList::LList(const LList& list);
LList& operator=(const LList& list);
friend ostream& operator<<(ostream& os, const LList& obj);
请更改这些和其他函数以传递const引用。如果您想了解为什么要更改此设置,如果您尝试执行此操作,则会立即看到问题:
LList list1;
LList list2;
//...
std::cout << list1 + list2;
operator <<
正在寻找非const LList
对象,但添加“inline”会返回一个临时LList
(这意味着返回值为const
})。由于您的重载operator <<
只接受非const LList
,代码将无法编译。
因此,您需要将operator <<
中的参数更改为const LList&
。
答案 1 :(得分:0)
您的列表类中有一个内置的“当前”指针。这是一个严重的设计错误。由于此错误,您无法正确定义函数。
这是一个设计错误,因为使用此设计,您无法迭代const
列表,这意味着,除了其他不好的事情之外,您无法对临时列表执行任何有用的操作。所以当你计算setA + setB
时,你不能将它分配给任何东西,因为要分配你需要迭代,所以你需要一个非{const}参数到operator=
和复制构造函数。但是你不能将临时绑定到非const引用。
即使您绕过复制构造函数和复制赋值运算符中的公共接口,并直接复制列表而不使用curr
,任何必须使用公共接口的用户函数都会遇到同样的问题。也就是说,setA + setB
将不能用作函数参数。您需要先将其分配给某个变量,然后将该变量传递给该函数。
您也无法获取列表并在迭代过程中将其传递给某个函数,并期望继续从您离开的位置进行迭代,因为迭代列表的任何内容都会更改curr
指针。
最好的解决方案是摆脱curr
成员并完成大部分论证const LList&
。虽然这不是onky解决方案,但是将当前指针内置到列表类中还有许多其他缺点,所以我不会谈论它们。
为了迭代列表,你必须提供一个可以在列表上来回转换的单独对象,以及一个可以在 const 列表上来回转换的单独变体。这被称为迭代器,如果你想在C ++中做任何事情,你需要阅读这个概念。
在您的情况下,迭代器可以是Node*
和const Node*
。您只需要提供返回列表中第一个节点的成员函数,这些函数已经存在。真正的图书馆也这样做。由于各种原因,它们通常将节点指针包装在单独的迭代器类中;但是对于一个简单的作业,这是没有必要的(尽管你可以这样做)。