本來這篇博客是不打算寫的,內容不是很難,對於我自己來講,更多的是為了突出細節。
- 所謂template friend functions,就是使友元函數本身成為模板。基本步驟:
1,在類定義的前面聲明每個模板函數。eg:template <typename T> void counts(); template <typename T> void report<>(T &);
2,在類聲明中再次將模板聲明為友元。
template <typename TT> class HasFriendT { .... friend void counts<TT>(); friend void report<>(Testclass<TT> &) };
聲明中<>指出這是模板具體化,注意模板具體化和函數具體化有點不一樣。對於report,<>可以為空,因為可以從函數參數推斷出模板類型參數。在聲明的例子中是:HasfriendT<TT>。然而,也可以使用report<HasFriendT<TT>> 來代替 report<> 。
但是counts沒有參數,因此必須使用模板參數語法(<TT>)來指明其具體化。還要注意的是,TT是Testclass類的參數類型。
3,為友元提供模板定義。這里的定義只是就“泛型”TT,每個函數定義一個就行。並不需要像函數顯式具體化那樣為每個特定的類型通通都定義。 - 好了,接下來看代碼:
1 #include <iostream> 2 3 using std::cout; 4 using std::endl; 5 6 template <typename T> void counts(); 7 template <typename T> void report(T &); 8 9 template <typename TT> 10 class HasFriendT 11 { 12 private: 13 TT item; 14 static int ct; 15 public: 16 HasFriendT(const TT & i) : item(i) { ct++; } 17 ~HasFriendT() { ct--; } 18 friend void counts<TT>(); 19 friend void report<HasFriendT<TT>>(HasFriendT<TT> &); 20 //note: use report<HasFriendT<TT>> not report<TT> 21 }; 22 23 template <typename T> 24 int HasFriendT<T>::ct = 0; 25 26 template <typename T> 27 void counts() 28 { 29 cout << "template size: " << sizeof(HasFriendT<T>) << "; "; 30 cout << "template counts(): " << HasFriendT<T>::ct << endl; 31 } 32 33 template <typename T> 34 void report(T & hf) 35 { 36 cout << hf.item << endl; 37 } 38 39 int main(void) 40 { 41 counts<int>(); 42 HasFriendT<int> hfi1(11); 43 HasFriendT<int> hfi2(22); 44 HasFriendT<double> hfi3(15.5); 45 46 report(hfi1); 47 report(hfi2); 48 report(hfi3); 49 50 cout << "counts<int>() output: \n"; 51 counts<int>(); 52 cout << "counts<double>() output: \n"; 53 counts<double>(); 54 55 return 0; 56 }
開始的時侯,在聲明模板時明明counts 和 report 的<>內都是typename T(即<typename T>),我想不明白為什么在class中friend void counts<TT>() 和 friend void report<HasFriendT<TT>>(HasFriendT<TT> &) <>內的參數就不一樣了呢(一個是<HasfriendT<TT>> 一個 是 <TT>)。后來仔細看了下,才發現report函數和counts函數處理的對象不一樣。report處理的是item,它是類HasFrriendT的成員數據,所以它的類型是<HasFriendT<TT>>。而counts處理的是一個靜態成員,對於靜態類成員,可以在類聲明之外使用單獨的語句進行初始化,這是因為靜態類是單獨存儲的,而不是對象的組成部分。也正如本文開頭所指出那樣:在countsde<>中, TT是Testclass類的參數類型。
- 不知到你有沒有發現上面的聲明中,一會用TT,一會用T。開始我也納悶,神經兮兮的認為它們的不同是不是隱含什么細節。后來將它們全部改成TT再編譯,發現沒什么問題。原來這只是一個泛型的符號而已。。當然,它們也可能真的存在什么不同,但現在我還沒有發現。