C++Primer Plus 第十四章代码重用:模板类和友元14.4.9
提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:模板类和友元14.4.9
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
2.模板类的约束模板友元函数
可以修改前一个示例,使友元函数本身成为模板。具体地说,为约束模板友元作准备,要使类的每个具体化都获得与友元匹配的具体化。这比非模板友元复杂些,包含以下3步。首先,在类定义的前面声明每个模板函数。
template <typename T> void counts();
template <typename T>void report(T &);
然后,在函数中再次将模板声明为友元。这些语句根据类模板参数的类型声明具体化:
template <typename TT>
class HasFriendT
friend void counts<TT>();
friend void report<>(HasFriendT<TT> &);
}:声明中的>指出这是模板具体化。对于 repon(),一可以为空,因为可以从函数参数推断出如下模板类型参数:HasFriendT
然而,也可以使用:
report<HasFriendT<TT>>(HasFriendT<TT>&)
但 counts()函数没有参数,因此必须使用模板参数语法()来指明其具体化。还需要注意的是,TT是HasFriendT类的参数类型。
同样,理解这些声明的最佳方式也是设想声明一个特定具体化的对象时,它们将变成什么样。例如,假设声明了这样一个对象:
HasFriendT<int>squack;
编译器将用int替换 TT,并生成下面的类定义:class HasFriendT
friend void counts<int>();
friend void report<>(HasFriendT<int> &);
基于 TT 的具体化将变为 int,基于 HasFriend的具体化将变为 HasFriend。因此,模板具体化counts( )和 report<HasFriendT>( )被声明为 HasFriendT类的友元。
程序必须满足的第三个要求是,为友元提供模板定义。程序清单14.23说明了这3个方面。请注意,程序清单 14.22包含1个 count()函数,它是所有 HasFriend 类的友元;而程序清单 14.23包含两个 count()函数,它们分别是某个被实例化的类类型的友元。因为count()函数调用没有可被编译器用来推断出所需具体化的函数参数,所以这些调用使用count和coount()指明具体化。但对于repor()调用,编译器可以从参数类型推断出要使用的具体化。使用>格式也能获得同样的效果:
report<HasFriendT<int>>(hfi2);/same as report(hfi2);
程序清单14.23 tmp2tmp.cpp
// tmp2tmp.cpp -- template friends to a template class
#include <iostream>
using std::cout;
using std::endl;
// template prototypes
template <typename T> void counts();
template <typename T> void report(T &);
// template class
template <typename TT>
class HasFriendT
{
private:
TT item;
static int ct;
public:
HasFriendT(const TT & i) : item(i) {ct++;}
~HasFriendT() { ct--; }
friend void counts<TT>();
friend void report<>(HasFriendT<TT> &);
};
template <typename T>
int HasFriendT<T>::ct = 0;
// template friend functions definitions
template <typename T>
void counts()
{
cout << "template size: " << sizeof(HasFriendT<T>) << "; ";
cout << "template counts(): " << HasFriendT<T>::ct << endl;
}
template <typename T>
void report(T & hf)
{
cout << hf.item << endl;
}
int main()
{
counts<int>();
HasFriendT<int> hfi1(10);
HasFriendT<int> hfi2(20);
HasFriendT<double> hfdb(10.5);
report(hfi1); // generate report(HasFriendT<int> &)
report(hfi2); // generate report(HasFriendT<int> &)
report(hfdb); // generate report(HasFriendT<double> &)
cout << "counts<int>() output:\n";
counts<int>();
cout << "counts<double>() output:\n";
counts<double>();
// std::cin.get();
return 0;
}
正如您看到的,counts和 counts报告的模板大小不同,这表明每种 T类型都有自己的友元函数 count( )。
3.模板类的非约束模板友元函数
前一节中的约束模板友元函数是在类外面声明的模板的具体化。int 类具体化获得int 函数具体化,依此类推。通过在类内部声明模板,可以创建非约束友元函数,即每个函数具体化都是每个类具体化的友元。对于非约束友元,友元模板类型参数与模板类类型参数是不同的:
template <typename T>
class ManyFriend
template <typename C,typename D> friend void show2(C &, D &);
程序清单 14.24是一个使用非约束友元的例子。其中,函数调用show2(hfl,hf2)与下面的具体化匹配:
void show2<ManyFriend<int>&,ManyFriend<int>&>(ManyFriend<int>&c,ManyFriend<int>&d);
因为它是所有ManyFriend具体化的友元,所以能够访问所有具体化的item成员,但它只访问了ManyFriend对象。
同样,show2(hfd,hf2)与下面具体化匹配:
void show2<ManyFriend<double>&,ManyFriend<int> &>(ManyFriend<double>&c,ManyFriend<int>&d);
它也是所有 ManyFriend 具体化的友元,并访问了ManyFriend对象的item 成员和 ManyFriend对象的 item 成员。
程序清单14.24 manyfrnd.cpp
// manyfrnd.cpp -- unbound template friend to a template class
#include <iostream>
using std::cout;
using std::endl;
template <typename T>
class ManyFriend
{
private:
T item;
public:
ManyFriend(const T & i) : item(i) {}
template <typename C, typename D> friend void show2(C &, D &);
};
template <typename C, typename D> void show2(C & c, D & d)
{
cout << c.item << ", " << d.item << endl;
}
int main()
{
ManyFriend<int> hfi1(10);
ManyFriend<int> hfi2(20);
ManyFriend<double> hfdb(10.5);
cout << "hfi1, hfi2: ";
show2(hfi1, hfi2);
cout << "hfdb, hfi2: ";
show2(hfdb, hfi2);
// std::cin.get();
return 0;
}
标签:友元,14.4,void,HasFriendT,C++,template,具体化,模板
From: https://blog.csdn.net/zhyjhacker/article/details/140088416