overloading extraction operator << as friend of class to display list

Dec 5, 2012 at 11:10pm
Having trouble with this, my prototype looks like this

friend void operator<<(ostream& outs, const List& rhs);

and my function to implement looks like this, but whenever i try to run it i get an error saying "'void List::operator<<(std::ostream&, List&)' must take exactly one argument|"


1
2
3
4
5
6
7
8
9
10
11
void List::operator<<(ostream& outs, List& rhs){

    ListNode *cur = head;
    outs << cur->item << " ";

    for (int i = 0; i < getLength(); i++){
        cur = cur->next;
        outs << cur->item << " ";
        return outs;
    }
}


If i try to make it have one argument, then in my header file I get an error saying it must take exact two parameters, so i'm pretty confused, any help is appreciated
Dec 5, 2012 at 11:49pm
Maybe something like this...

prototype
 
    friend std::ostream & operator<<(std::ostream & outs, const List & rhs); 


definition
1
2
3
4
5
6
7
std::ostream & operator<<(std::ostream & outs, const List & rhs)
{  

    // put the required code here

    return outs;
}
Dec 5, 2012 at 11:52pm
In the definition above, operator<< takes 3 arguments. It takes a a pointer to List, a reference to ostream, and a reference to list.

Now, of course, you just read that and are thinking.. "It does not take a pointer to List! What's this bozo talking about?!" but, in fact, it does. Every member function of a class receives a pointer to the instance of the object it should be working on. You can access it as this within the member function. You don't use the rhs parameter anyway, so I assume you knew this on an intuitive level.

If you define operator << as a member of a class, the relative order of the parameters will be wrong.

For instance:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
ostream&  List::operator<<(ostream& os ) // should be a const here.
{
    ListNode * cur = head ;
    // ...
    return os ;
}

int main()
{
    List list ;
    cout << list ;  // error, no match for overloaded operator<<.
    list << cout ;  // this works! but..  man, that just looks wrong!
    list.operator<<(cout) ;   // also works.
}


So, we come to the friend function. Note that member functions do not need to be friend functions, because they already have access to the internals of the class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  // friend declaration in List definition, then...

ostream& operator<<(ostream& os, const List & list)
{
    const ListNode * current = list.head ;
    while ( current )
    {
        os << current->item << " " ;
        current = current->next ;
        // if we did a return here, the loop would only execute one time.
    }

    // return when the loop is done.
    return os ;
}


Notice that the function is not a member of List, and now the parameters are in the correct order, so everything should work as we expect.
Last edited on Dec 5, 2012 at 11:54pm
Dec 6, 2012 at 3:25am
Now if i try to do that it tells me "ListNode was not declared in this scope"...I think that's why it needs to be friend?
Dec 6, 2012 at 4:54am
If ListNode is defined in your List class you need to use List::ListNode.
Dec 6, 2012 at 5:13am
so

List::ListNode ostream& operator<<(ostream& os, const List & list)

that's the header?
Dec 6, 2012 at 5:20am
On line 5, the only place that ListNode was used in the snippet of code I gave above and doubtless where the error message your compiler gives pointed you to, you need to use List::ListNode so the line becomes:

const List::ListNode * current = list.head ;
Dec 6, 2012 at 5:24am
thank you so much
Topic archived. No new replies allowed.