轉載html
http://blog.sina.com.cn/s/blog_69dd1a090101fc59.html數據結構
問題始於學習數據結構,本身編寫一個單鏈表,其中用到了重載輸出運算符<<,我寫的大約這樣:函數
1 template <class T> class List{ 2 friend std::ostream& operator << (std::ostream& os,const List<T>& slist); 3 //…… 4 };
用vs2008可編譯,但沒法連接:沒法解析的外部符號……學習
後來上網查改成spa
1 template <class T> class List{ 2 friend std::ostream& operator << <>(std::ostream& os,const List<T>& slist); 3 //…… 4 };
就能夠了。不知因此然,查了下《C++ Primer》才弄明白。code
在類模板中能夠出現三種友元聲明:
(1)普通非模板類或函數的友元聲明,將友元關係授予明確指定的類或函數。
(2)類模板或函數模板的友元聲明,授予對友元全部實例的訪問權。
(3)只授予對類模板或函數模板的特定實例的訪問權的友元聲明。htm
要注意的是,友元函數並不是成員函數,是改變了它對類成員的訪問權限。對象
(1)沒有什麼好說的,如:blog
1 template<class T> 2 3 class A{ 4 5 friend void fun(); 6 7 //... 8 9 };
此例中fun可訪問A任意類實例中的私有和保護成員get
(2)
1 template<class T> 2 3 class A{ 4 5 template<class T> 6 7 friend void fun(T u); 8 9 //... 10 11 };
這時友元使用與類不一樣的模板形參,T能夠是任意合法標誌符,友元函數能夠訪問A類的任何類實例的數據,即不論A的形參是int,double或其餘均可以。
(3)
1 template<class T> 2 3 class A{ 4 5 friend void fun<T>(T u); 6 7 //... 8 9 };
此時fun只有訪問類中特定實例的數據。換句話說,此時具備相同模板實參的fun函數與A類纔是友元關係。即假如調用fun時其模板實參爲int,則它只具備A<int>的訪問權限。固然friend void fun<T>(T u);中<>中的T能夠是任意類型,好比int,double等
回到原問題,按(3)可改成:
template <class T> class List{ friend std::ostream& operator << <T>(std::ostream& os,const List<T>& slist); //…… };
按(2)可改成:
1 template <class T> class List{ 2 3 template <class T> 4 friend std::ostream& operator << (std::ostream& os,const List<T>& slist); 5 //…… 6 };
在這裏其實二者實現的最終效果同樣的,由於調用輸出運算符時須要訪問的類實例的對象是它自己,因此形參T在第一種改法中必定匹配。