2014-11-06 4 views
0

Мне нужна помощь при перегрузке оператора «+» для добавления двух двусвязных списков. Я не могу скомпилировать свою программу из-за ошибки «no match for operator = ...». Я уже перегрузил оператор '=', но попытаюсь напечатать результат добавления к std-выводу. Я также перегрузил оператор < <. Был попыткой выяснить, что не так в течение многих часов без успеха. Любые подсказки, как решить эту проблему и/или решения для нее, очень приветствуются. Это назначение для моего класса ООП. Спасибо заранее!Перегрузка операторов для добавления двух двусвязных списков

EDIT: Основная идея кода - реплицировать набор. Перегруженные операторы «+» должны работать как объединение и «*» в качестве пересечения. Я изо всех сил стараюсь, чтобы профсоюз был правильно напечатан на выход std. «+ =», похоже, работает нормально. '< <' работает хорошо, но только когда дело доходит до распечатки одного списка.


EDIT: Ошибки, произведенные компилятором (г ++, выход из кода :: блоков, я удалил заметки компилятора):

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 
} 
+5

TL; DR! Пожалуйста, сузите свой код только к тем частям, с которыми у вас проблемы. Лучше всего, если вы создаете [Минимальный, полный и проверенный пример] (http://stackoverflow.com/help/mcve) и показываете только это. Кроме того, здесь мало людей, которые читают польский (?), Поэтому, пожалуйста, оставляйте комментарии и выходите на английском языке. –

+0

Извините за это, впервые разместив здесь. Обновит его как можно скорее. –

+0

Процедура такова: вы делите свой код на один исходный файл из 10-100 строк или около того, убедитесь, что вы по-прежнему получаете сообщение об ошибке, о котором хотите получить помощь, а затем публикуете исходный файл ** в полном объеме и без редактирования **. Не забудьте включить ** неотредактированные ** сообщения об ошибках (или несколько начальных строк, если список слишком длинный). Если то, что вы опубликовали, невозможно скопировать, как есть и скомпилировано, чтобы получить ту же самую ошибку, с которой вы хотите получить помощь, вы тратите время на все. –

ответ

0

У вас есть встроенный «текущий» указатель в вашем классе списка. Это серьезная ошибка дизайна. Из-за этой ошибки вы не можете правильно определить свои функции.

Это ошибка дизайна, потому что при таком дизайне вы не можете перебирать списки const, а это означает, среди прочего, что вы не можете ничего использовать с временными списками.Поэтому, когда вы вычисляете setA + setB, вы не можете назначить его чему-либо, потому что для назначения вам потребуется итерация, поэтому вам нужен аргумент non-const для operator= и для конструктора копирования. Но вы не можете привязать временную ссылку к неконстантной ссылке.

Даже если вы обходите открытый интерфейс в конструкторе копирования и операторе присваивания копий и скопируете список напрямую, не используя curr, у вас будет такая же проблема с любой пользовательской функцией, которая должна использовать открытый интерфейс. То есть setA + setB не будет использоваться в качестве аргумента функции. Сначала вам нужно назначить его некоторой переменной, а затем передать эту переменную функции.

Вы также не можете взять список и передать его некоторой функции в середине итерации и ожидать продолжения итерации с места, которое вы оставили, потому что все, что итерирует список, меняет указатель curr.

Лучшее решение для избавления от члена curr и использования большинства ваших аргументов const LList&. Хотя это не основное решение, есть много других недостатков в том, что текущий указатель встроен в класс списка, поэтому я не буду говорить о них.

Для того, чтобы итерировать список, вы должны предоставить отдельный объект, который может перемещаться вперед и назад по списку, и отдельный вариант, который может перемещаться взад и вперед по списку const. Это называется итератором, и вам нужно прочитать эту концепцию, если вы хотите что-либо сделать на C++.

В вашем случае итераторы могут быть Node* и const Node*. Вам нужно только предоставить функции-члены, которые возвращают первый узел в списке, который у вас уже есть. Реальные библиотеки делают то же самое. Обычно они обертывают указатель узла в отдельном классе итератора по разным причинам; но для простой домашней работы это не обязательно (хотя вы можете сделать это, если хотите).

2

Там находится одна свирепо ошибка ваш код:

Node* begin() { curr = head; } 

Этот код вызывает неопределенное поведение, так как вы не возвращаете значение. Оно должно быть таким:

Node* begin() { curr = head; return curr; } 

Кроме того, вы должны передать ваши LList по константной ссылке в функциях, которые не изменяет 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); 

Пожалуйста, измените эти и другие фу nctions для передачи ссылок const. Если вы хотите понять, почему вы должны изменить это, вы будете видеть проблему немедленно, если вы попытаетесь это сделать:

LList list1; 
LList list2; 
//... 
std::cout << list1 + list2; 

operator << ищет неконстантных LList объектов, но добавление «инлайн» возвращает временный LList (что будет означать, что возвращаемое значение будет const). Код не будет компилироваться из-за вашего перегруженного operator <<, принимающего только неконстантный LList.

Поэтому вам необходимо изменить свой параметр в operator << на const LList&.

+0

Я бы также предложил реализовать оператор + в качестве функции друга. – besworland

+0

Спасибо, Пол. Проблема решена, добавив параметр const в параметр, переданный функции. Ценю вашу помощь! –

+0

@ besworland не могли бы вы предоставить более подробную информацию, почему это было бы лучше? –

Смежные вопросы