详见http://www.cnblogs.com/assemble8086/archive/2011/10/02/2198308.html
类模板的友元有三种声明:
1)非模板类的友元类或友元函数
1 template <typename T> 2 class Rect{ 3 public: 4 friend void create(); 5 };
create函数成为所有Rect类实例化的友元,它可以访问全局对象;可以使用全局指针访问非全局对象;可以创建自己的对象;可以访问独立对象的模板类的静态数据成员。
1 template <typename T> 2 class Rect{ 3 public: 4 friend void create(Rect<T>&); 5 };
这种声明使得create函数传入了Rect类的实例,create(Rect<T>&)将成为Rect<T>类的友元。
2)绑定的友元类模板或友元函数
1 template <typename T> 2 class Rect; 3 template <typename T> 4 ostream& operator<<(ostream&,const Rect<T>&); 5 6 7 template <typename T> 8 class Rect{ 9 public: 10 friend ostream& operator<< <T>(ostream&,const Rect<T>&); 11 };
该声明表示类模板的实例和它的友元之间是一种一对一的映射关系。
将友元模板函数声明在类模板中,定义在类模板之外。当模板函数被声明为类模板的友元时,在函数名之后必须紧跟模板实参表,用来代表该友元声明指向函数模板的实例。否则友元函数会被解释为一个非模板函数,链接时无法解析。
3)非绑定的友元类模板或友元函数
该声明表示类模板的实例和它的友元之间是一种一对多的映射关系。对于非约束友元,友元模板类型参数与模板类类型参数是不同的。
1 template <typename T> 2 class Rect{ 3 public: 4 Rect(const T&i):item(i){} 5 template <typename T2,typename T3> 6 friend void show(T2&,T3&); 7 private: 8 T item; 9 }; 10 11 template <typename T2,typename T3> 12 void show(T2& rect1,T3& rect2) 13 { 14 cout << rect1.item << " , " << rect2.item << endl; 15 }
通过在类内部声明模板,可以创建非约束友元函数,即每个函数具体化都是每个类具体化的友元。
1 int main() 2 { 3 Rect<int> R1(10); 4 Rect<double> R2(7.5); 5 show(R1,R2); 6 }
show是所有Rect具体化的友元,并访问了Rect<int>对象的item成员和Rect<double>对象的item成员。