Search code examples
c++linker-errorsfriend

What does "friend std::ostream& operator<<(std::ostream& out, LinkedList& list)" mean?


So I was given an assignment with starter code to implement a linked list (which I have done with an unsorted doubly linked list successfully) and in the starter code in the given header file there was a friend declaration that seems to have the goal of allowing me to print the linked list using the cout statement. This is the header file; note that I wrote everything in the private section.

#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, which was also part of the starter code, the teacher wrote cout << list; which leads me to believe the goal of the friend statement in the header file was to allow list to be printed to the console easily. Normally I wouldn't care but if I don't comment out the cout << list; statements then the linker gives me the following error for every instance of cout << list;

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

My question is, what does friend std::ostream& operator<<(std::ostream& out, LinkedList& list) mean and why does cout << list; cause this error? The code executes fine without the statements and since I'm using the instructor's makefile to assemble the assignment, I figure that isn't the issue.

app.cpp is as follows

#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;
}

Solution

  • what does friend std::ostream& operator<<(std::ostream& out, LinkedList& list) mean

    The friend declaration declares a non-member function, and makes it friend of the class, meaning it can access the private and protected members of the class LinkedList.

    and why does cout << list; cause this error?

    Since it's just a declaration, you need to define it by yourself. That's why you get an undefined reference linker error.

    You might define it inside the class (and defined inline)

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

    Or define it outside of the class:

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

    BTW: I suggest you to make the 2nd parameter type const LinkedList&; it should not be modified inside the operator<<.