//第二十三模板 15模和友元
//模板类也可以声明为友元,模板类的友元共分三种情况
//1 非模板友元类或者友元函数
//2 通用模板类或者友元函数
//3 特定类型的模板友元类或者友元函数
//1非模板的友元类和友元函数
//我们可以将任何类或者函数声明为模板类的友元,这样由模板类生成的每个具体类都会正确处理友元类或者友元函数,就好像友元关系已经在具体化的类中声明了一样
/*#include <iostream>
using namespace std;
const int size=10;
template<class T>
class num
{
public:
num(int Tsize=size);
num(const num&r);
~num(){delete []pt; }
num&operator=(const num&);
T&operator[](int offset){ return pt[offset]; }
const T&operator[](int offset)const
{
return pt[offset];
}
int GetSize()const{ return numsize; }
friend void print(num<T>);//友元
private:
int numsize;
T *pt;
};
//定义友元
template<class T>
void print(num<T> sw)
{
cout<<"friend函数执行"<<endl;
//for(int i=0; i<sw.numsize; i++){
//cout<<"num["<<i<<"]: \t"<<sw.pt[i]<<endl;
//}
}
//带一个参数的构造函数
template<class T>
num<T>::num(int size):numsize(size)
{
cout<<"执行构造函数"<<endl;
pt = new T[size];
for(int i=0; i<size; i++){
pt[i] = 0;
}
cout<<"numsize:"<<numsize<<endl;
}
//定义的复制构造函数
template<class T>
num<T>::num(const num&r)
{
numsize = r.GetSize();
pt = new T[numsize];
for(int i=0; i<numsize; i++){
pt[i] = r[i];
}
}
//重载运算符=
template<class T>
num<T>&num<T>::operator=(const num&r)
{
if(this == &r){
return *this;
delete []pt;
numsize = r.GetSize();
pt = new T[numsize];
for(int i=0; i<numsize; i++){
pt[i] = r[i];
}
}
return *this;
}
int main()
{
num<int>one;
for(int i=0; i<one.GetSize(); i++)
{
one[i] = i*2;
cout<<one[i]<<endl;
}
print(one);
//for(int i=0; i<one.GetSize(); i++){
//cout<<"num["<<i<<"]: \t"<<one.pt[i]<<endl;
//cout<<one.pt[i]<<endl;
//}
return 0;
}*/
//正确的方法
/*
#include <iostream>
using namespace std;
const int size=10;
template<class T>
class num
{
public:
num(int Tsize=size);
num(const num&r);
~num(){delete []pt; }
num&operator=(const num&);
T&operator[](int offset){ return pt[offset]; }
const T&operator[](int offset)const
{
return pt[offset];
}
int GetSize()const{ return numsize; }
friend void print(num<T>);//友元
private:
int numsize;
T *pt;
};
void print(num<int>sw)
{
cout<<"friend函数执行"<<endl;
for(int i=0; i<sw.numsize; i++){
cout<<"num["<<i<<"]: \t"<<sw.pt[i]<<endl;
}
}
void print(num<double>sw)
{
cout<<"friend函数执行"<<endl;
for(int i=0; i<sw.numsize; i++){
cout<<"num["<<i<<"]: \t"<<sw.pt[i]<<endl;
}
}
//带一个参数的构造函数
template<class T>
num<T>::num(int size):numsize(size)
{
cout<<"执行构造函数"<<endl;
pt = new T[size];
for(int i=0; i<size; i++){
pt[i] = 0;
}
cout<<"numsize:"<<numsize<<endl;
}
//定义的复制构造函数
template<class T>
num<T>::num(const num&r)
{
numsize = r.GetSize();
pt = new T[numsize];
for(int i=0; i<numsize; i++){
pt[i] = r[i];
}
}
//重载运算符=
template<class T>
num<T>&num<T>::operator=(const num&r)
{
if(this == &r){
return *this;
delete []pt;
numsize = r.GetSize();
pt = new T[numsize];
for(int i=0; i<numsize; i++){
pt[i] = r[i];
}
}
return *this;
}
int main()
{
num<int>one;
num<double>two;
for(int i=0; i<one.GetSize(); i++)
{
one[i] = i*2;
two[i] = i*5;
}
print(one);
print(two);
return 0;
}*/
//由于print()函数被声明为一个非模板友元函数,因此它并不是一个模板函数,而只是使用了模板的参数T,这样我们必须在定义函数时具体化模板参数T,该函数才被正确的创建,
//2 通用模板友元类的友元函数
//友元函数被声明为一个模板函数,因此我们不用显示式具体化友元函数的定义部分
//class num{
//public:
// template<class T1>
// friend void print(num<t1>);
//}
//template<class T1>将print()友元函数说明为一个模板函数,这样print()函数便可适用于任何类型,注意,通用模板友元函数与模板类的模板参数是不同的,模板类的模板参数是T,而模板友元函数的模板能数是T1
/*
#include <iostream>
using namespace std;
const int size=10;
template<class T>
class num
{
public:
num(int Tsize=size);
num(const num&r);
~num(){delete []pt; }
num&operator=(const num&);
T&operator[](int offset){ return pt[offset]; }
const T&operator[](int offset)const
{
return pt[offset];
}
int GetSize()const{ return numsize; }
//friend void print(num<T>);//友元
//定义模板友元函数
template<class T1>
friend void print(num<T1>);
//函数就变成了一个通用的模板友元函数,又叫非约束模板友元函数
private:
int numsize;
T *pt;
};
//这里的template<class T1>是函数所表示的模板
template<class T1> void print(num<T1>sw)
{
cout<<"friend函数执行!";
for(int i=0; i<sw.GetSize(); i++){
cout<<"num["<<i<<"]:\t"<<sw.pt[i]<<endl;
}
}
//带一个参数的构造函数
template<class T>
num<T>::num(int size):numsize(size)
{
cout<<"执行构造函数"<<endl;
pt = new T[size];
for(int i=0; i<size; i++){
pt[i] = 0;
}
cout<<"numsize:"<<numsize<<endl;
}
//定义的复制构造函数
template<class T>
num<T>::num(const num&r)
{
numsize = r.GetSize();
pt = new T[numsize];
for(int i=0; i<numsize; i++){
pt[i] = r[i];
}
}
//重载运算符=
template<class T>
num<T>&num<T>::operator=(const num&r)
{
if(this == &r){
return *this;
delete []pt;
numsize = r.GetSize();
pt = new T[numsize];
for(int i=0; i<numsize; i++){
pt[i] = r[i];
}
}
return *this;
}
int main()
{
num<int>one;
num<double>two;
for(int i=0; i<one.GetSize(); i++)
{
one[i] = i*2;
two[i] = i*5;
}
print(one);
print(two);
return 0;
}*/
/*
// 3 特定类型模板友元函数
#include <iostream>
using namespace std;
const int size=10;
template <template <class T> class TT, class T>
ostream & operator<< (ostream &out, const TT<T> &tt);
template<class T>
class num
{
public:
num(int Tsize=size);
num(const num&r);
~num(){delete []pt; }
num&operator=(const num&);
T&operator[](int offset){ return pt[offset]; }
const T&operator[](int offset)const
{
return pt[offset];
}
int GetSize()const{ return numsize; }
friend ostream &operator<< <>(ostream &out, const num<T> &tt);
private:
int numsize;
T *pt;
};
template<template <class T> class TT, class T>
ostream &operator <<(ostream &out, const TT<T> &tt)
{
out<<"调用operator<<函数"<<endl;
for(int i=0; i<tt.GetSize(); i++){
out<<"["<<tt[i]<<"]"<<endl;
}
return out;
}
//带一个参数的构造函数
template<class T>
num<T>::num(int size):numsize(size)
{
cout<<"执行构造函数"<<endl;
pt = new T[size];
for(int i=0; i<size; i++){
pt[i] = 0;
}
cout<<"numsize:"<<numsize<<endl;
}
//定义的复制构造函数
template<class T>
num<T>::num(const num&r)
{
numsize = r.GetSize();
pt = new T[numsize];
for(int i=0; i<numsize; i++){
pt[i] = r[i];
}
}
//重载运算符=
template<class T>
num<T>&num<T>::operator=(const num&r)
{
if(this == &r){
return *this;
delete []pt;
numsize = r.GetSize();
pt = new T[numsize];
for(int i=0; i<numsize; i++){
pt[i] = r[i];
}
}
return *this;
}
int main()
{
num<int>one;
num<double>two;
for(int i=0; i<one.GetSize(); i++)
{
one[i] = i*2;
two[i] = i*5;
}
cout<<one;
cout<<two;
return 0;
}*/
//该程序与前一个程序同样的结果,不过该程序,也就是在模板类外部声明特定模板友元函数比前一个程序复杂
//1 我们必须在模板类前面声明模板友元函数,
//2 在模板类中具体化模板友元函数
//3 为这个特定的模板友元函数提供模板定义