之前这篇文章是转载过来的,当时觉得读得就囫囵吞枣,最近来看这个文章写的也不是很清晰,如果对C++的语法知识想进一步的了解的话,《C++ Primer》还是王道啊
模板类的友元分3类:
- 非模板友元
- 约束(bound)模板友元,即友元的类型取决于类被实例化时的类型。
- 非约束(undound)模板友元,即友元的所有具体化都是类的每一个具体化的友元。
模板类的非模板友元函数
请看下面这段代码
template<class T>
class HasFriend
{
friend void counts(); //friend to all HaFriend instantiations
};
上诉声明使counts()函数成为模板所有实例化的友元。通俗一点就是说无论模板类的通过什么类型来进行实例化,函数void count()都是这些实例化的友元
需要说明的是友元的声明仅仅制订了访问的权限,而非一个通常意义上的函数声明。如果我们希望用户可以调用这个友元函数的话,那么我们就必须在友元声明之外再专门对这个友元函数进行一次声明。
虽然说这个友元函数可以是非模板函数,但是为友元函数提供模板类参数,必须提供特定的具体化,如HasFriend。
要提供模板类参数,必须指明具体化:
template<class T>
class HasFriend
{
friend void report(HasFriend<T> & ); // bound template friend
//balabala
};
也就是说,带HasFriend参数的report()将成为HasFriend类的友元函数。同样,带HasFriend参数的report()将是report()的一个重载版本——它将是HasFriend类的友元。
report()本省并不是模板函数,而只是使用一个模板作参数。这意味着必须为要使用的友元定义显示具体化:
void report(HasFriend & ) {…} //explicit specialization for short
void report(HasFriend & ) {…} //explicit specialization for int
模板类的约束模板友元函数
修改前一个上面的范例,使友元函数本身成为模板。使类的每一个具体化都获得与友元匹配的具体化。即《C++ Primer》中说的一对一关系;
包含以下三步:
1. 首先,在类定义的前面声明每个模板函数:
template <typename T> void counts();
template <typename T> void report(T &);
- 然后在函数中再次将模板声明为友元。这些语句根据类模板参数的类型声明具体化:
template <typename TT>
class HasFriend
{
//HasFriend的每个实例将相同实例化的counts函数声明为友元
friend void counts<TT>();
friend void report<>(HasFriend<TT> &);
//balabala
};
上述声明中的<>指出这是模板具体化。对于report(),<>可以为空,这是因为可以从函数参数推断出模板类型参数(HasFriend)。不过,也可以使用report
class HasFriend<int>
{
friend void counts<int>();
friend void report<>(HasFriend<int> &);
//balabala
};
于是,模板具体化counts()和report
template <typename T>
void counts() { cout << HasFriend<T>::x << endl;}
template <typename T>
void report(T & hf) {cout << hf.x << endl;}
调用时,counts()需要提供具体化参数类型。report()只需直接调用,例如:
counts(); //调用HasFriend的友元函数
HasFriend hfdb;
report(hfdb); //调用HasFriend的友元函数
模板类的非约束模板友元函数
通过在类内部声明友元函数模板,可以创建非约束友元函数,即每个模板函数实例都是每个类的每个实例的友元,当使用这种类型的友元模板函数时是不需要前置声明的:
template <typename T>
class ManyFriend
{
template <typename C,typename D> friend void show(C &,D &);
};
在类外定义该友元:
template <typename C,typename D>
void show(C & c,D & d){ //balabala }
假如创建ManyFriend类对象(hfi1)和ManyFriend类对象(hfi2),传递给show(),那么编译器将生成如下具体化定义:
void show<ManyFriend<int> &,ManyFriend<double> &>
(ManyFriend<int> & c,ManyFriend<double> & d){ //balabala }
这是还是需要自己总结一下,因为这篇文章看了好多遍,总是忘记bound friend template function 和unbound friend template function 的区别,所以还是要自己总结一下;也感叹一下,有 博客就是好,相当于笔记本了,有问题就翻看
对于bound friend template function来说,它主要是侧重每一个类的具体化都有一个友元函数具体与之相对应;这种适合友元函数需要访问的只有一个类模板具象化;譬如func_这个友元函数中,只需要一个Myclass的具象化,这时就可以用bound friendtemplate function;
而对于unbound friend template function来说,每一个友元函数的具现化都是每一个模板类的具现化的友元,也就是无论友元函数中关于类模板的具现化的类型是什么,这个友元函数都是和他们匹配的;unbound friend template function更适合函数中有两种或两种以上模板类的具现化的类型。
我觉得这次我应该记住了!!!