求好心人解答~~
1.怎么把模板类设置为友元??模板函数 模板类。
2.设置的时候 需要具体化吗?? 是不是 可以具体化 也可以不具体??
同问0 |浏览435| 收藏0 |分享
非模板友元
声明一个常规友元
template
class HasFriend
{
public:
friend void counts();
}
上边的声明使counts()函数成为模板所有实例化的友元
counts()函数不是通过对象调用的(它是友元,不是成员函数),也没有对象参数,那么它如何访问HasFriend对象的呢
有很多种可能性。它可以访问全局对象;可以使用全局指针访问非全局对象;可以创建自己的对象;可以访问独立对象的模板类
的静态数据成员。
如果要为友元函数提供械板类参数,可以如下所示来进行友元声明。要提供模板类参数,必须指明基体化
template
class HasFriend
{
friend void report(HasFriend &);
}
report()本身并不是模板函数,而只是使用一个模板作参数。这意味着必须要使用的友元定义显式基体化:
void report(HasFriend &){....}
void report(HasFriend &){...};
也就是说report(HasFriend &)将成为HasFriend类的友元。
复制代码
include
using std::cout;
using std::cin;
using std::endl;
template
class HasFriendT
{
private:
TT item;
static int ct;
public:
HasFriendT(const TT & i):item(i){ct++;};
~HasFriendT(){ct--;};
friend void counts();
friend void report(HasFriendT &);
};
template
int HasFriendT::ct = 0;
void counts()
{
cout<<"int count: "<::ct<<";";
cout<<"double count:"<::ct<}
void report(HasFriendT & hf)
{
cout<}
void report(HasFriendT & hf)
{
cout<}
int main()
{
counts();
HasFriendT hfi1(10);
counts();
HasFriendT hfdb(10.5);
report(hfi1);
HasFriendT hfi2(20);
report(hfi2);
report(hfdb);
counts();
cin.get();
}
//int count: 0;double count:0
//int count: 1;double count:0
//10
//20
//10.5
//int count: 2;double count:1
复制代码
约束模板友元函数友元的类型取决于类被实例化时的类型
可以修改上边的示例,使友元函数本身成为模板。具体的说,为约束模板友元作准备,要使类的每一个基体
化都获得与友元匹配的基体化。这需要3部
1首先,在类定义的前面声明每个模板函数
template void counts()
template void report(T &);
2然后,在函数中再次将模板声明为友元。这些语句根据类模板参数的类型声明具体化:
template
class HasFriendT
{
friend void counts();
friend void report<>(HasFriendT &);
};
声明中的<>指出这是模板具体化。对于report(),<>可以为空,因为可以从函数参数推断出如下模板类型参数:
HasFriendT
然而也可以使用:
report>(HasFriendT &)
但是counts()函数没有参数,因此必须使用模板参数语法()来指明其基体化。还需要注意的是,
TT是HasFriendT类的参数类型。
同样,理解这些声明的最佳方式也是设想声明一个特定具体化的对象时,它们将变成什么样子。例如,
假设声明了这样一个对象
HasFriendT squack;
编译器将用int替换TT,并生成下面的类定义
class HasFriendT
{
friend void counts();
friend void report<>(HasFriendT &);
}
3第三个条件是为友元提供模板定义
看例子:
复制代码
include
using std::cout;
using std::cin;
using std::endl;
template void counts();
template void report(T &);
template
class HasFriendT
{
private:
TT item;
static int ct;
public:
HasFriendT(const TT & i):item(i){ct++;};
~HasFriendT(){ct--;};
friend void counts();
friend void report<>(HasFriendT &);
};
template
int HasFriendT::ct = 0;
template
void counts()
{
cout<<"template size: "<)<<";";
cout<<"template counts():"<::ct<}
template
void report(T & hf)
{
cout<}
int main()
{
counts();
HasFriendT hfi1(10);
HasFriendT hfi2(20);
HasFriendT hfdb(10.5);
report(hfi1);
report(hfi2);
report(hfdb);
cout<<"counts output:n";
counts();
cout<<"counts() output:n";
counts();
cin.get();
}
//template size: 4;template counts():0
//10
//20
//10.5
//counts output:
//template size: 4;template counts():2
//counts() output:
//template size: 8;template counts():1
复制代码
counts 和couts 报告的模板大小不同,这样每种T类型都有自己的友元函数count();
非约束模板友元
友元的所有具体化都是类的每一个具体化的友元
上边说的约束模板友元函数是在类外面声明的模板的具体化。int类型具体化获得int函数具体化,
依此类推。通过在类内部声明模板,可以创建非约束友元函数,即每个函数具体化都是每个类具体化的友元。
对于非约束友元,友元模板类型参数与模板类类型参数是不同的:
template
{
template
friend void Show2(C &,D &)
}
上边是一个使用非约束友元函数的例子,其中,函数调用show2(hfi1,hfi2)与下面的具体化匹配:
void Show2 &,ManyFriend &>(ManyFriend & c,ManyFriend & d);
因为它是所有ManyFriend 具体化的友元,所以能够访问所有具体化的item成员,但它只访问了ManyFriend对象。
同样Show2(hfd,hfd2)与下面具体化匹配:
void Show2(ManyFirend &,ManyFirend &>(ManyFirend & c,ManyFirend & d);
它也是所有ManyFriend具体化的友元,并访问了ManyFirend 对象的item成员和ManyFriend对象的item成员
复制代码
include
using std::count;
using std::cout;
using std::endl;
template
class ManyFriend
{
private:
T item;
public:
ManyFriend(const T & i):item(i){};
template
friend void Show2(C &,D &);
};
template
void Show2(C & c,D & d)
{
cout<}
int main()
{
ManyFriend hfi1(10);
ManyFriend hfi2(20);
ManyFriend hfdb(10.5);
cout<<"hfi1, hfi2";
Show2(hfi1,hfi2);
cout<<"hfdb,hfi2: ";
Show2(hfdb,hfi2);
std::cin.get();
}
//hfi1, hfi210,20
//hfdb,hfi2: 10.5,20
非模板友元
声明一个常规友元
template
class HasFriend
{
public:
friend void counts();
}
上边的声明使counts()函数成为模板所有实例化的友元
counts()函数不是通过对象调用的(它是友元,不是成员函数),也没有对象参数,那么它如何访问HasFriend对象的呢
有很多种可能性。它可以访问全局对象;可以使用全局指针访问非全局对象;可以创建自己的对象;可以访问独立对象的模板类
的静态数据成员。
如果要为友元函数提供械板类参数,可以如下所示来进行友元声明。要提供模板类参数,必须指明基体化
template
class HasFriend
{
friend void report(HasFriend &);
}
report()本身并不是模板函数,而只是使用一个模板作参数。这意味着必须要使用的友元定义显式基体化:
void report(HasFriend &){....}
void report(HasFriend &){...};
也就是说report(HasFriend &)将成为HasFriend类的友元。
复制代码
include
using std::cout;
using std::cin;
using std::endl;
template
class HasFriendT
{
private:
TT item;
static int ct;
public:
HasFriendT(const TT & i):item(i){ct++;};
~HasFriendT(){ct--;};
friend void counts();
friend void report(HasFriendT &);
};
template
int HasFriendT::ct = 0;
void counts()
{
cout<<"int count: "<::ct<<";";
cout<<"double count:"<::ct<}
void report(HasFriendT & hf)
{
cout<}
void report(HasFriendT & hf)
{
cout<}
int main()
{
counts();
HasFriendT hfi1(10);
counts();
HasFriendT hfdb(10.5);
report(hfi1);
HasFriendT hfi2(20);
report(hfi2);
report(hfdb);
counts();
cin.get();
}
//int count: 0;double count:0
//int count: 1;double count:0
//10
//20
//10.5
//int count: 2;double count:1
复制代码
约束模板友元函数友元的类型取决于类被实例化时的类型
可以修改上边的示例,使友元函数本身成为模板。具体的说,为约束模板友元作准备,要使类的每一个基体
化都获得与友元匹配的基体化。这需要3部
1首先,在类定义的前面声明每个模板函数
template void counts()
template void report(T &);
2然后,在函数中再次将模板声明为友元。这些语句根据类模板参数的类型声明具体化:
template
class HasFriendT
{
friend void counts();
friend void report<>(HasFriendT &);
};
声明中的<>指出这是模板具体化。对于report(),<>可以为空,因为可以从函数参数推断出如下模板类型参数:
HasFriendT
然而也可以使用:
report>(HasFriendT &)
但是counts()函数没有参数,因此必须使用模板参数语法()来指明其基体化。还需要注意的是,
TT是HasFriendT类的参数类型。
同样,理解这些声明的最佳方式也是设想声明一个特定具体化的对象时,它们将变成什么样子。例如,
假设声明了这样一个对象
HasFriendT squack;
编译器将用int替换TT,并生成下面的类定义
class HasFriendT
{
friend void counts();
friend void report<>(HasFriendT &);
}
3第三个条件是为友元提供模板定义
看例子:
复制代码
include
using std::cout;
using std::cin;
using std::endl;
template void counts();
template void report(T &);
template
class HasFriendT
{
private:
TT item;
static int ct;
public:
HasFriendT(const TT & i):item(i){ct++;};
~HasFriendT(){ct--;};
friend void counts();
friend void report<>(HasFriendT &);
};
template
int HasFriendT::ct = 0;
template
void counts()
{
cout<<"template size: "<)<<";";
cout<<"template counts():"<::ct<}
template
void report(T & hf)
{
cout<}
int main()
{
counts();
HasFriendT hfi1(10);
HasFriendT hfi2(20);
HasFriendT hfdb(10.5);
report(hfi1);
report(hfi2);
report(hfdb);
cout<<"counts output:n";
counts();
cout<<"counts() output:n";
counts();
cin.get();
}
//template size: 4;template counts():0
//10
//20
//10.5
//counts output:
//template size: 4;template counts():2
//counts() output:
//template size: 8;template counts():1
复制代码
counts 和couts 报告的模板大小不同,这样每种T类型都有自己的友元函数count();
非约束模板友元
友元的所有具体化都是类的每一个具体化的友元
上边说的约束模板友元函数是在类外面声明的模板的具体化。int类型具体化获得int函数具体化,
依此类推。通过在类内部声明模板,可以创建非约束友元函数,即每个函数具体化都是每个类具体化的友元。
对于非约束友元,友元模板类型参数与模板类类型参数是不同的:
template
{
template
friend void Show2(C &,D &)
}
上边是一个使用非约束友元函数的例子,其中,函数调用show2(hfi1,hfi2)与下面的具体化匹配:
void Show2 &,ManyFriend &>(ManyFriend & c,ManyFriend & d);
因为它是所有ManyFriend 具体化的友元,所以能够访问所有具体化的item成员,但它只访问了ManyFriend对象。
同样Show2(hfd,hfd2)与下面具体化匹配:
void Show2(ManyFirend &,ManyFirend &>(ManyFirend & c,ManyFirend & d);
它也是所有ManyFriend具体化的友元,并访问了ManyFirend 对象的item成员和ManyFriend对象的item成员
复制代码
include
using std::count;
using std::cout;
using std::endl;
template
class ManyFriend
{
private:
T item;
public:
ManyFriend(const T & i):item(i){};
template
friend void Show2(C &,D &);
};
template
void Show2(C & c,D & d)
{
cout<}
int main()
{
ManyFriend hfi1(10);
ManyFriend hfi2(20);
ManyFriend hfdb(10.5);
cout<<"hfi1, hfi2";
Show2(hfi1,hfi2);
cout<<"hfdb,hfi2: ";
Show2(hfdb,hfi2);
std::cin.get();
}
//hfi1, hfi210,20
//hfdb,hfi2: 10.5,20
根据《C++ Primer》第三版16.4节的叙述,C++类模板友元分为以下几种情况
1.非模板友元类或友元函数。 书上给了一个例子:
class Foo{
void bar();
};
template
class QueueItem{
friend class foobar;
friend void foo();
friend void Foo::bar();
//....
};
很简单,跟非模板类没什么区别,有一点需要注意,如果要把函数和类生命为友元,前面不需要声明或定义。但是如果要把类成员函数声明为友元,则前面必须有类的定义(注意不是声明,是定义),因为一个类成员只能由该类的定义引入 。
2.绑定的友元类模板或函数模板。 例子如下:
template
class foobar{ ...};
template
void foo(QueueItem);
template
class Queue{
void bar();
//...
};
template
class QueueItem {
friend class foobar ;
friend void foo (QueueItem);
friend void Queue ::bar();
//...
};
需要注意两点:
a.与非模板函数或类不同,模板函数或类声明为友元之前必须在前面声明过 ,否则无法通过编译。
b.注意红字部分,那几个Type不能少。比如对于函数foo,如果少了的话编译器会将其作为非模板函数对待,也就是说,对于QueueItem,编译器会查找void foo(QueueItem),而对templatevoid foo(QueueItem)视而不见,如果没找到非模板函数则会报错。
3.非绑定友元类模板或函数模板。 举例如下:
template
class QueueItem {
template
friend class foobar;
template
friend void foo(QueueItem<T>);
template
friend void Queue<T>::bar();
//...
};
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。