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

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

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:模板类和友元14.4.9


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档


模板类和友元14.4.9

模板类声明也可以有友元。模板的友元分3类:
非模板友元;约束(bound)模板友元,即友元的类型取决于类被实例化时的类型;非约束(unbound)模板友元,即友元的所有具体化都是类的每一个具体化的友元。
下面分别介绍它们。

1.模板类的非模板友元函数

在模板类中将一个常规函数声明为友元:

template <class T>
class HasFriend
public:
friend void counts();//friend to all HasFriend instantiations
...

上述声明使 counts()函数成为模板所有实例化的友元。例如,它将是类 hasFriend和 HasFriend的友元。
counts()函数不是通过对象调用的(它是友元,不是成员函数),也没有对象参数,那么它如何访问HasFriend对象呢?有很多种可能性。它可以访问全局对象;可以使用全局指针访问非全局对象;可以创建自己的对象:可以访问独立于对象的模板类的静态数据成员。
假设要为友元函数提供模板类参数,可以如下所示来进行友元声明吗?

friend void report(HasFriend &);// possible?

答案是不可以。原因是不存在 HasFriend 这样的对象,而只有特定的具体化,如 HasFriend。要提供模板类参数,必须指明具体化。例如,可以这样做:

template <class T>
class HasFriend
friend void report(HasFriend<T>&);//bound template friend

为理解上述代码的功能,想想声明一个特定类型的对象时,将生成的具体化:

HasFriend<int> hf;

编译器将用int替代模板参数T,因此友元声明的格式如下:

Class HasFriend<int>
friend void report(HasFriend<int>&);// bound template friend

也就是说,带 HasFriend参数的 repor( )将成为 HasFriend类的友元。同样,带 HasFriend参数的report( )将是report( )的一个重载版本–它是 Hasfriend类的友元。注意,repor()本身并不是模板函数,而只是使用一个模板作参数。这意味着必须为要使用的友元定义显式具体化:

void report(HasFriend<short>&)(...);//explicit specialization for shortvoid report(HasFriend<int>&)(...);//explicit specialization for int

程序清单 14.22 说明了上面几点。HasFriend 模板有一个静态成员 ct。这意味着这个类的每一个特定的具体化都将有自己的静态成员。count()方法是所有 HasFriend 具体化的友元,它报告两个特定的具体化(HasFriend和 HasFriend)的 ct的值。该程序还提供两个repon()函数,它们分别是某个特定 HasFriend 具体化的友元。

程序清单14.22 frnd2tmp.cpp

// frnd2tmp.cpp -- template class with non-template friends
#include <iostream>
using std::cout;
using std::endl;

template <typename T>
class HasFriend
{
private:
    T item;
    static int ct;
public:
    HasFriend(const T & i) : item(i) {ct++;}
    ~HasFriend()  {ct--; }
    friend void counts();
    friend void reports(HasFriend<T> &); // template parameter
};

// each specialization has its own static data member
template <typename T>
int HasFriend<T>::ct = 0;

// non-template friend to all HasFriend<T> classes
void counts()
{
    cout << "int count: " << HasFriend<int>::ct << "; ";
    cout << "double count: " << HasFriend<double>::ct << endl;
}

// non-template friend to the HasFriend<int> class
void reports(HasFriend<int> & hf)
{
    cout <<"HasFriend<int>: " << hf.item << endl;
}

// non-template friend to the HasFriend<double> class
void reports(HasFriend<double> & hf)
{
    cout <<"HasFriend<double>: " << hf.item << endl;
}

int main()
{
    cout << "No objects declared: ";
    counts();
    HasFriend<int> hfi1(10);
    cout << "After hfi1 declared: ";
    counts();
    HasFriend<int> hfi2(20);
    cout << "After hfi2 declared: ";
    counts();
    HasFriend<double> hfdb(10.5);
    cout << "After hfdb declared: ";
    counts(); 
    reports(hfi1);
    reports(hfi2);
    reports(hfdb);
    // std::cin.get();
    return 0; 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值