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.