C++Primer Plus 第十四章代码重用:模板类和友元14.4.9 ----002

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;
}

  • 17
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值