Вопрос о перегрузке оператора, не являющегося членом <<, в классе связанного списка в С++ 98

Может ли кто-нибудь помочь мне с этим вопросом, пожалуйста? Для справочной информации у меня есть три класса: Account.h с Account.cpp, Node.h с Node.cpp, LinkedList.h с Linkedlist.cpp и demo.cpp, который содержит int main(). Все текущие функции работают, за исключением распечатки связанного списка, что является основой моего вопроса.

В вопросе конкретно сказано:

Реализуйте перегруженную функцию operator <<, не являющуюся членом, которая использует operator << из Account, чтобы вы могли выполнять такие операции, как:

cout << MyLinkedList << endl;

Я скопировал определенные части своего кода, связанные с этим вопросом, из LinkedList.cpp и Account.cpp, потому что это будет слишком долго, если я вставлю все это сюда.

Код из LinkedList.cpp с перегруженной функцией operator <<, «еще не работающей», показан ниже: Обратите внимание, что value_type является typedef для Account.

#include "LinkedList.h"
    
LinkedList::value_type LinkedList::getCurrent() const {
    if (current != NULL) {
        return current->getData();
    } else {
        return value_type();
    }
}
    
ostream& operator << (ostream& out, const LinkedList& list) { // not working, compile error!
    value_type current = getCurrent();
    while (current != NULL) {
        out << "(" << acc.getName() << "," << acc.balance() << ")" << endl;
    }
    return out;
}

Код от Account.cpp показан ниже:

ostream& operator << (ostream& out, const Account& acc)
{
    out << "(" << acc.getName() << "," << acc.balance() << ")" << endl;
    return out;
}

Это объявления классов для моего файла node.h:

#ifndef TEKAAI_NODE
#define TEKAAI_NODE

#include "Account.h"

class Node
{
    public:
        // members that are externally visible 
        
        // Below are Member functions
        
        // specifying value_type to Account using typedef
        typedef Account value_type;
        
        // Default constructor
        
        Node();     
        
        // Parameter Constructors
        
        Node(const value_type& initial_data, Node* initial_link);
        
        ~Node();    //destructor
        
        void setNext(Node* n);
        
        void setPrevious(Node* p);
        
        Node* getNext() const;
        
        Node* getPrevious() const;
        
        // the data getters and setters
        // Pre-condition: Current has been initialized 
        // Post-condition: set data
        void setData(const value_type& i);
        
        // Pre-condition: Data has been initialized
        // Post-condition: returns stored data
        value_type getData() const;
        
    private:
        value_type data;    //the data held by the node
        Node* next;         //a pointer to the next node
        Node* previous;     //a pointer to the previous node
};
#endif

Это объявления классов в моем файле LinkedList.h:

#ifndef TEKAAI_LINKEDLIST_H
#define TEKAAI_LINKEDLIST_H

#include "Account.h"
#include "Node.h"
#include <iostream>

class LinkedList
{
    public:
        typedef Account value_type;
        // Members that are externally visible
        
        // These are Member functions
        
        // Constructors
            
        LinkedList();   
        
        // Destructor
        
        ~LinkedList();
        
        void addToHead(const value_type& account); 
        
        void addToTail(const value_type& account);
        
        void addCurrent(const value_type& account);
        
        value_type removeFromHead();
        
        value_type removeFromTail();
        
        value_type removeFromCurrent();
        
        // Pre-condition: LinkedList contains nodes
        // Post-condition: moves current to the head 
        void start();  

        // Pre-condition: LinkedList contains nodes
        // Post-condition: moves current to the tail
        void end();
        
        // Pre-condition: LinkedList contains nodes
        // Post-condition: moves current one node to the right
        void forward();  
        
        // Pre-condition: LinkedList contains nodes
        // Post-condition: moves current one node to the left
        void back(); 
        
        // Pre-condition: LinkedList contains nodes
        // Post-condition: returns the value of data account stored 
        // in current node
        value_type getCurrent() const;
        
        // Pre-condition: LinkedList is initialized, containing 
        // nodes
        // Post-condition: returns the length of the list
        int length();
    
    private:
        Node* head;
        Node* tail;
        Node* current;
};  
ostream& operator << (ostream& out, const LinkedList& list);

#endif  

Как вы можете видеть в объявлении класса LinkedList выше, мне приходится работать с ними, чтобы попытаться распечатать мой связанный список. Я хотел бы услышать ваши мысли, возможно ли распечатать мой связанный список, используя одну из вышеперечисленных функций, а также используя перегруженный оператор << из учетной записи, как указано в вопросе.

Спасибо.

ПЛЮС ПРИМЕЧАНИЕ. Просто чтобы вы знали, что я могу распечатать свой связанный список, используя функцию «Node * getHead () const;» который возвращает голову при перегрузке оператора <<, но я просто искал помощь, если можно распечатать связанный список без использования функции getHead(). Я предполагаю, что наш лектор просто баловался с нами, пытаясь заставить нас сойти с ума своей лабораторной деятельностью.

Нам не нужен весь ваш код, но нам нужен минимальный воспроизводимый пример. Пожалуйста, прочитайте ссылку и сделайте один.

HolyBlackCat 19.04.2023 09:19

«Обратите внимание, что value_type — это typedef для учетной записи…». Было бы лучше, если бы вы просто опубликовали MRE.

Jason 19.04.2023 09:30

Пожалуйста, покажите также полный текст вывода компилятора, в чем ошибка? Без минимального воспроизводимого примера или ошибки компилятора у нас очень мало шансов вам помочь. Наверняка LinkedList нельзя скопировать, но вы передаете его оператору по значению, обязательно используйте ссылку

Alan Birtles 19.04.2023 09:30

@HolyBlackCat, я отредактировал и опубликовал все свои объявления классов для класса LinkedList. Как вы думаете, можно ли распечатать мой связанный список, используя одну из функций выше, а также используя перегруженный оператор >> из класса Account??

Jac Investigator 19.04.2023 14:25
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
54
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Во-первых, ваши operator<< должны принимать свои вторые параметры по константной ссылке, а не по значению, например:

ostream& operator << (ostream& out, const Account& acc)
ostream& operator << (ostream& out, const LinkedList& list)

Во-вторых, да, можно использовать оператор Account внутри оператора LinkedList. Вам нужно что-то эквивалентное следующему (поскольку вы не предоставили полные объявления классов):

ostream& operator << (ostream& out, const LinkedList& list) {
    LinkedList::Node *cur = list.getFirst();
    while (cur != NULL) {
        out << cur->getData();
        cur = cur->getNext();
    }
    return out;
}

ОБНОВЛЕНИЕ: теперь, когда вы опубликовали объявление класса LinkedList, я вижу, что оно не предлагает ничего похожего на метод getFirst(). У него есть методы start() и forward() для итерации списка, но нет метода, указывающего, когда итерация достигла конца списка.

Итак, у вас есть несколько вариантов:

  • добавьте новый метод, чтобы указать, что getCurrent() безопасно вызывать:
class LinkedList
{
    public:
        ...        
        bool hasCurrent() const;
        value_type getCurrent() const;        
        ...    
};  
bool LinkedList::hasCurrent() const {
    return (current != NULL);
}

LinkedList::value_type LinkedList::getCurrent() const {
    return current->getData();
}
ostream& operator << (ostream& out, LinkedList& list) {
    list.start();
    while (list.hasCurrent()) {
        out << list.getCurrent();
        list.forward();
    }
    return out;
}
  • измените свой метод getCurrent(), чтобы он возвращал объект Account по указателю, а не по значению, чтобы он мог возвращать указатель NULL, когда итерация находится в конце списка:
class Node
{
    public:
        ...        
        value_type& getData();
        ...
};
LinkedList::value_type* LinkedList::getCurrent() {
    if (current != NULL) {
        return &(current->getData());
    } else {
        return NULL;
    }
}
ostream& operator << (ostream& out, LinkedList& list) {
    Account *cur;
    list.start();
    while ((cur = list.getCurrent()) != NULL) {
        out << *cur;
        list.forward();
    }
    return out;
}
  • сделайте оператор LinkedListfriend класса LinkedList, чтобы он мог напрямую обращаться к частному члену head:
class LinkedList
{
    public:
        ...
        friend ostream& operator << (ostream& out, const LinkedList& list);
        ...

    private:
        Node* head;
        ... 
};  

ostream& operator << (ostream& out, const LinkedList& list);
ostream& operator << (ostream& out, const LinkedList& list) {
    Node *cur = list.head;
    while (cur != NULL) {
        out << cur->getData();
        cur = cur->getNext();
    }
    return out;
}

Привет @Remy Lebeau, спасибо за ответ. К вашему сведению, я отредактировал свой пост, включив в него объявления классов для LinkedList. Как вы думаете, можно ли распечатать мой связанный список, используя одну из функций класса, а также используя перегруженный оператор << из класса Account?

Jac Investigator 19.04.2023 14:21

@TekaaiKaewaniti, учитывая существующие методы в классе LinkedList, нет. Я обновил свой ответ альтернативными решениями.

Remy Lebeau 19.04.2023 16:52

Другие вопросы по теме