本来这篇博客是不打算写的,内容不是很难,对于我自己来讲,更多的是为了突出细节。
- 所谓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再编译,发现没什么问题。原来这只是一个泛型的符号而已。。当然,它们也可能真的存在什么不同,但现在我还没有发现。
时间: 2024-10-24 12:26:45