2016-06-29 14 views
1

Also bekam ich eine Aufgabe mit Starter-Code, um eine verkettete Liste zu implementieren (was ich mit einer unsortierten doppelt verknüpften Liste erfolgreich gemacht habe) und im Starter-Code in der angegebenen Header-Datei gab es eine Friend-Deklaration, die das Ziel zu haben scheint damit ich die verknüpfte Liste mit der cout-Anweisung drucken kann. Dies ist die Header-Datei. Beachten Sie, dass ich alles im privaten Bereich geschrieben habe.Was bedeutet "friend std :: ostream & operator << (std :: ostream & out, LinkedList & list)"?

#ifndef _LINKED_LIST_ 
#define _LINKED_LIST_ 

#include <ostream> 

class LinkedList 
{ 
public: 
    LinkedList(); 
    ~LinkedList(); 

    void add(char ch); 
    bool find(char ch); 
    bool del(char ch); 

    friend std::ostream& operator<<(std::ostream& out, LinkedList& list); 

private: 
    struct node 
    { 
     char data; 
     node * next; 
     node * prev; 
    }; 
    node * head, * tail; 
}; 

#endif // _LINKED_LIST_ 

In main, die auch Teil des Starters Code war, schrieb der Lehrer cout << list; die mich führt das Ziel der Freund-Anweisung in der Header-Datei zu glauben, war Liste zu ermöglichen leicht an die Konsole zu drucken. Normalerweise würde ich nicht egal, aber wenn ich kommentiert Sie nicht die cout << list; Aussagen dann der Linker gibt mir die folgenden Fehler für jede Instanz von cout << list;

app.o: In function 'main': 
[code directory]/app.cpp:[line the statement is on]: undefined reference to 
'operator<<(std::ostream&, LinkedList&)' 

Meine Frage ist, was bedeutet friend std::ostream& operator<<(std::ostream& out, LinkedList& list) bedeuten und warum tut cout << list; diesen Fehler verursachen? Der Code läuft gut ohne die Anweisungen und da ich das Makefile des Instruktors verwende, um den Auftrag zusammenzustellen, denke ich, dass das nicht das Problem ist.

app.cpp ist als

#include <iostream> 
#include "linkedlist.h" 

using namespace std; 

void find(LinkedList& list, char ch) 
{ 
    if (list.find(ch)) 
     cout << "found "; 
    else 
     cout << "did not find "; 
    cout << ch << endl; 
} 

int main() 
{ 
    LinkedList list; 

    list.add('x'); 
    list.add('y'); 
    list.add('z'); 
    cout << list; 
    find(list, 'y'); 

    list.del('y'); 
    cout << list; 
    find(list, 'y'); 

    list.del('x'); 
    cout << list; 
    find(list, 'y'); 

    list.del('z'); 
    cout << list; 
    find(list, 'y'); 

    return 0; 
} 
+1

Es bedeutet, dass Sie deklariert, friended, und am wichtigsten, sind * mit * 'std :: ostream & operator << (std :: ostream & out, LinkedList & Liste);', aber nie wirklich * definiert * es in einer Übersetzungseinheit das ist mit deinem Code verbunden. Erklären, dass es der erste Schritt war; Sie müssen es noch implementieren. Unabhängig davon sollte der zweite Parameter idealerweise ein const-Verweis und nicht nur ein Verweis sein, da Ausgabeoperatoren das zu schreibende Objekt nur selten ändern. – WhozCraig

Antwort

9

folgt, was friend std::ostream& operator<<(std::ostream& out, LinkedList& list)

Die friend declaration hier zunächst eine nicht-Member-Funktion erklärt, bedeutet das und macht es Freund der Klasse, es bedeutet, kann auf die privaten und geschützten Mitglieder der Klasse LinkedList zugreifen.

und warum verursacht cout << list; diesen Fehler?

Da es nur eine Deklaration ist, müssen Sie es selbst definieren. Aus diesem Grund erhalten Sie einen undefinierten Referenz-Link-Fehler.

Man könnte es innerhalb der Klasse definieren (dh definiert Inline)

class LinkedList 
{ 
    ... 
    friend std::ostream& operator<<(std::ostream& out, LinkedList& list) { 
     // output something 
     return out; 
    } 
    ... 
}; 

Oder es außerhalb der Klasse definieren:

std::ostream& operator<<(std::ostream& out, LinkedList& list) { 
    // output something 
    return out; 
} 

BTW: Ich schlage vor, Sie den zweiten Parameter-Typ zu machen const LinkedList& ; Es sollte nicht innerhalb der operator<< geändert werden.

+0

Ich habe die zweite Funktion, die Sie in der cpp-Implementierungsdatei geschrieben haben, definiert, aber ich erhalte immer noch einen Fehler außerhalb des Bereichs für Knoten, aktuell und Kopf. –

+1

@LegionDaeth Kompilierfehler? Bitte zeigen Sie die Fehlermeldung an. Wie benutzt man "Kopf"? Ist es "list.head"? – songyuanyao

+1

Ich habe versucht, mit list.head und list.node, aber ich bekomme eine "ungültige Verwendung von 'struct LinkedList :: node'" Fehler und ein "Strom wurde nicht als Fehler deklariert" in Bezug auf "list.node * current;". Ich habe den Code zu der Frage hinzugefügt, um zu verdeutlichen, was ich geschrieben habe. –

3

Das Ziel von std::ostream& operator<<(std::ostream& out, LinkedList& list) eigentlich ist in der Lage zu sein, e. G. std::cout << someList;

Ein Teil Ihrer Aufgabe besteht nun darin, einen solchen Operator zu schreiben (und da Sie dies bisher noch nicht getan haben, erhalten Sie den Linker-Fehler ...);

class LinkedList 
{ 
    /* ... */ 
}; 

std::ostream& operator<<(std::ostream& out, LinkedList& list) 
{ 
    /* output the list however it is appropriate */ 
} 

Das alles ist in Ordnung so weit - nur ein einziges Problem: es wird außerhalb Ihrer Klasse, wie diese geschrieben werden, wie der Betreiber außerhalb der Klasse definiert ist, ist es nur die öffentliche Schnittstelle der Zugriff auf LinkedList-Klasse.

Und hier kommt die Friend-Deklaration ins Spiel: Mit dieser Deklaration erlauben Sie explizit operator<< auch auf die privaten Mitglieder zuzugreifen; in Ihrem Fall vor allem die Struktur und die Kopf-und Heck-Elemente, die sonst alle für den Betreiber nicht zugänglich gewesen wäre.

+0

Ich kopierte diese Funktion wörtlich, aber ich bekomme immer noch einen Fehler außerhalb des Bereichs für Knoten, Kopf und Strom, die ein Teil meines Ausgabealgorithmus sind. –

+0

@LegionDaeth Sind Sie dem Vorschlag von songyuanyao gefolgt, dem Listenparameter 'const'-ness hinzuzufügen? Dann müssen Sie es sowohl bei der Friend-Deklaration als auch bei der Implementierung hinzufügen, sonst erhalten diese verschiedene Operatoren. – Aconcagua

0

Sie haben richtig geraten, dass das Ziel dieser Funktion darin besteht, eine Instanz der Klasse in den bereitgestellten Ausgabestrom zu drucken. Wenn er in diesem Kontext verwendet wird (zwei Argumente, ein Verweis auf einen Ausgabestrom und eine Referenz auf ein Objekt irgendeiner Art, und das Zurückgeben des Streams), wird der Operator << üblicherweise als Stream-Insertion-Operator bezeichnet.

Die Kopfzeile erklärt die Freundesfunktion , und es wird in der main-Funktion, die vom Kursleiter geschrieben wurde, referenziert. Wenn Sie die Zuweisung vollständig kreditieren möchten, müssen Sie diese Funktion implementieren. Das Qualifikationsmerkmal friend bedeutet, dass es sich um eine freie Funktion und nicht um eine Elementfunktion handelt, die jedoch auf Objekte mit geschützten und privaten Elementen LinkedList zugreifen kann.