-1

Я работаю над классом связанного списка, который содержит частный класс вложенных узлов. Я хочу продвинуть n узлов вперед в моем списке, используя оператор перегруженного сложения, но clang дает мне ошибку «перегруженный» оператор + 'должен быть унарным или двоичным оператором (имеет 3 параметра) ». Я думал, что неявный этот параметр исчез, когда вы объявили его как функцию друга.Перегрузка оператора добавления для указателей на вложенные классы

Первый мой файл заголовка

template <class T> 
class List 
    { 

    private: 

    class ListNode 
    { 
     public: 

     ListNode(); 


     ListNode(const T& ndata); 


     friend ListNode* operator+(const ListNode* &node, int n); 

     ListNode* next; 

     ListNode* prev; 

    }; 

    public: 
    friend ListNode* operator+(const ListNode* &node, int n); 

и моя реализация выглядит следующим образом:

template <class T> 
typename List<T>::ListNode* List<T>::ListNode::operator+(const ListNode* &node, int n) 
{ 
    ListNode* current = node; 

    while (n--){ 
     if (current->next != 0) 
      current = current->next; 
    } 
    return current; 
} 
+0

Жаль, что ошибка была неправильной. Возобновлено. – NathanOliver

+0

Друг-функция на самом деле не является членом, поэтому вы не можете определить ее вне линии таким образом. На самом деле единственный разумный способ определения таких функций является встроенным. –

ответ

1

В принципе, проблема с тем, что вы пытаетесь сделать, что это oveloading оператор на указатели , Это problematic. Упрощая свой код как можно больше для точки, следующие не строят:

class foo{}; 

foo *operator+(foo *, int) { 
    return nullptr; 
} 

int main() {} 

попытка дает:

$ g++ gl.cpp 
gl.cpp:5:26: error: ‘foo* operator+(foo*, int)’ must have an argument of class or enumerated type 
foo *operator+(foo *, int) { 

Если вы действительно хотите использовать operator+, самый простой способ может следует использовать форму оператора-оператора:

template<class T> 
class List { 
    class ListNode {  ... 
    public: 
     ListNode &operator+(int n) { 
      ListNode *current = this; 

      while (n--) 
       if (current->next != 0) 
        current = current->next; 

      return *current; 
     } 
    }; 
    ... 
}; 

Однако, это немного вводит в заблуждение, так как вы фактически не добавляя целое число к узлу, а скорее получая следующий узел. next метод, вероятно, понятнее:

template<class T> 
class List { 
    class ListNode {  ... 
    public: 
     ListNode *next(int n) { 
      ListNode *current = this; 

      while (n--) 
       if (current->next != 0) 
        current = current->next; 

      return current; 
     } 
    }; 
    ... 
}; 
+0

Я хотел поставить узел вместо этого, но я все равно получаю ту же ошибку, я смущен тем, как определить его как свободную функцию/что это значит. –

+0

@DarylDrake См. Обновление. –

1

Как уже говорилось, перегрузка операторов указателей, является проблематичным, и опять же, проще всего сделать было бы сделать operator+ функцию-член. Тем не менее, есть способ получить нужное поведение ...

Хитрость заключается в том, чтобы обернуть указатель в объект, который действует как указатель (обычно известный как iterator).

рабочий пример, чтобы продемонстрировать:

class List { 
    struct Node { 
     Node* next; int data; 
    }; 
    Node* m_head{0}; 

public: 
    // the fake pointer type. 
    struct Iter { 
     Iter(Node* initial = 0) 
      : m_base(initial) {} 
     Node* operator->() 
     { return m_base; } 
     bool operator!=(const Iter& other) const 
     { return m_base != other.m_base; } 
    private: 
     Node* m_base; 
    }; 

    // get head as fake pointer. 
    Iter head() 
    { return m_head; } 
    void push_front(const int&); 
}; 

void List::push_front(const int& x) 
{ 
    Node* n = new Node; 
    n->data = x; 
    n->next = m_head; m_head = n; 
} 

// non-member operator. 
List::Iter operator+(List::Iter i, int count) 
{ 
    for (; count > 0 && i != 0; count--) 
     i = i->next; 
    return i; 
} 

int main(int argc, char* argv[]) 
{ 
    List list; 
    for (int i = 0; i < 10; i++) 
     list.push_front(i); 
    for (auto i = list.head(); i != 0; i = i+1) 
     std::cout << i->data << ' '; 
    std::cout << std::endl; 
    return 0; 
} 

Для более продвинутых примера см here.

+0

Хорошее использование итераторов! –

+0

@AmiTavory Спасибо! –

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

  • Нет связанных вопросов^_^