目录
分类
一、非模板友元:友元函数不是模板函数,而是利用模板类参数生成的函数;
代码
分析
运行结果
二、约束模板友元:模板类实例化时,每个实例化的类对应一个友元函数;并且这个模板友元适用多种类模板(最常用)
代码
分析
1)构造约束模板友元函数的步骤
2)编译器在实例化某种数据类型的模板类时,也会实例化这种数据类型的模板函数
3)友元模板函数适应于多种类模板,如AA和BB;
4)优点(与非模板友元对比)
运行结果
三、非约束模板友元:模板实例化时,如果实例化了n个类,也会实例化n个友元函数,每个实例化的类都拥有n个友元函数;(模板 函数,实际开发一般不用)
代码
分析
运行结果
分类
模板类的友元函数有三类
1)非模板友元:友元函数不是模板函数,而是利用模板类参数生成的函数;
2)约束模板友元:模板类实例化时,每个实例化的类对应一个友元函数;
3)非约束模板友元:模板实例化时,如果实例化了n个类,也会实例化n个友元函数,每个实例化的类都拥有n个友元函数;
一、非模板友元:友元函数不是模板函数,而是利用模板类参数生成的函数;
代码
#include<iostream>
using namespace std;
template<class T1,class T2>
class AA//AA是类模板,是类的通用描述,改变不存在叫AA的类
{
private:
T1 m_x;
T2 m_y;
public:
friend void show(AA<T1,T2>&a)
{
cout<<"x="<<a.m_x<<",y="<<a.m_y<<endl;
}
AA(const T1 x,const T2 y):m_x(x),m_y(y){
}
};
int main()
{
//是类名AA<int,string>
AA<int,string>aa(88,"我是一只小猫咪");
show(aa);
return 0;
}
分析
非模板友元:友元函数不是模板函数,而是利用模板类参数生成的函数,只能在类内实现。
该方法生成的友元函数只能用于该模板类,不能用于其他模板类;
运行结果
二、约束模板友元:模板类实例化时,每个实例化的类对应一个友元函数;并且这个模板友元适用多种类模板(最常用)
代码
#include<iostream>
using namespace std;
//约束模板友元:模板实例化时,每个实例化的类对应一个友元函数
template<typename T>
void show(T&a); //第一步:在模板类定义的前面,声明友元函数,为了让模板类知道友元函数模板的存在
template<class T1,class T2>
class AA//AA是类模板,是类的通用描述,改变不存在叫AA的类
{
private:
T1 m_x;
T2 m_y;//第二步:在模板类中,再次声明友元函数模板,让编译器知道需要实例化的友元函数模板
friend void show<>(AA<T1,T2>&a); //这行代码让类模板和函数模板扯上关系
public:
AA(const T1 x,const T2 y):m_x(x),m_y(y){}
};
template<class T1,class T2>
class BB//AA是类模板,是类的通用描述,改变不存在叫AA的类
{
private:
T1 m_x;
T2 m_y;//第二步:在模板类中,再次声明友元函数模板,让编译器知道需要实例化的友元函数模板
friend void show<>(BB<T1,T2>&a); //这行代码让类模板和函数模板扯上关系
public:
BB(const T1 x,const T2 y):m_x(x),m_y(y){}
};
//编译器在实例化某种数据类型的模板类时,也会实例化这种数据类型的模板函数
//通用版本友元函数
template<typename T> //第三步:友元函数模板的定义
void show(T&a)
{
cout<<"通用:x="<<a.m_x<<",y="<<a.m_y<<endl;
}
//因为友元函数是函数模板,所以可以有具体化版本
//具体化版本友元函数
template<>
void show(AA<int,string>&a) //第四步:具体化版本
{
cout<<"具体:x="<<a.m_x<<",y="<<a.m_y<<endl;
}
int main()
{
//是类名AA<int,string>
AA<int,string>aa(88,"我是一只小猫咪");
show(aa); //使用具体化的版本
BB<char,string>bb('2',"我是一只小猫咪");
show(bb); //使用通用的版本 ,友元函数适应多种函数模板
return 0;
}
分析
1)构造约束模板友元函数的步骤
①第一步:在模板类定义的前面,声明友元函数,为了让模板类知道友元函数模板的存在
②第二步:在模板类中,再次声明友元函数模板,让编译器知道需要实例化的友元函数模板
③第三步:友元函数模板的定义
④第四步:具体化版本
2)编译器在实例化某种数据类型的模板类时,也会实例化这种数据类型的模板函数
3)友元模板函数适应于多种类模板,如AA和BB;
4)优点(与非模板友元对比)
①可以具体化
②支持多个版本
运行结果
三、非约束模板友元:模板实例化时,如果实例化了n个类,也会实例化n个友元函数,每个实例化的类都拥有n个友元函数;(模板 函数,实际开发一般不用)
代码
#include<iostream>
using namespace std;
//非类模板约束的友元函数:模板实例化时,每个函数都是每个每个类的友元
template<class T1,class T2>
class AA//AA是类模板,是类的通用描述,改变不存在叫AA的类
{
private:
T1 m_x;
T2 m_y;
template<typename T> //把show函数模板声明为友元函数模板
friend void show(T&a); //和普通函数声明为友元函数是类似的
public:
AA(const T1 x,const T2 y):m_x(x),m_y(y){}
};
//通用版本函数模板
template<typename T>
void show(T&a)
{
cout<<"通用:x="<<a.m_x<<",y="<<a.m_y<<endl;
}
//函数模板具体化版本
template<>
void show(AA<int,string>&a)
{
cout<<"具体:x="<<a.m_x<<",y="<<a.m_y<<endl;
}
int main()
{
//是类名AA<int,string>
AA<int,string>a1(88,"我是一只小猫咪");
show(a1); //使用具体化的版本
AA<char,string>a2('2',"我是一只小猫咪");
show(a2); //使用通用的版本
return 0;
}
分析
1)非约束模板的友元函数,模板实例化时,如果实例化了n个类,也会实例化n个友元函数,每个实例化的类都拥有n个友元函数;不科学
2)对于程序员来说,这种友元函数和约束模板友元函数是没有区别的;