文章目录
一、函数模板
在写函数时常常会出现两个很相似的函数但我们却需要在c语言里面敲两次
但是在c++里我们可以咏函数的方式来做到
例如:
交换函数时我们如果想交换int间和double间的值的话就要这么写
void swap(int & x,int & y)
{
int tmp=x;
x=y;
y=tmp;
}
void swap(double & x,double & y)
{
double tmp=x;
x=y;
y=tmp;
}
但是也可以通过模板的方式来实现
template <class T>
void swap(T & x,T & y)
{
T tmp=x;
x=y;
y=tmp;
}
在使用的时候会根据输入实参的不同生成互为重载关系的函数但是形式一样仅仅只是形参不同;
函数模板:
template <class 类型参数 1,class 类型参数 2······>
返回值类型 模板名(形参表)
{
函数体;
}
函数模板可以有不止一个类型在类型参数表
template<class T1,class T2>
T2 print(T1 arg1,T2 arg2){
cout<<arg1<<" "<<arg2<<endl;
returb arg2;
}
求数组最大元素的MaxElement函数模板
template<classT>
T MaxElement(T a[],int size)//size是元素个数
{
T temMax=a[0];
for(int i=1;i<size;++i)
if(temMax<a[i])
temMax=a[i];
return temMax;
}
模板实例化是模板->函数
参数实例化是不同参数不同效果
函数模板可以重载,形参表或者类型参数表不同可以构成重载效果
如:
template<class T1,class T2>
void print(T1 arg1,T2 arg2){
cout =<<arg1<<" "<<arg2<<endl;
}
template<class T>
void print(T arg1,T arg2){
cout =<<arg1<<" "<<arg2<<endl;
}
template<class T1,class T2>
void print(T1 arg1,T1 arg2){
cout =<<arg1<<" "<<arg2<<endl;
}
函数模板与函数的匹配次序
①参数匹配的普通函数
②参数匹配的模板函数
③实参经过自动类型转换后能匹配的普通函数
④报错
例:
#include<iostream>
using namespace std;
template<class T>
T Max(T a,T b){
cout<<"TemplateMax"<<endl;
return 0;
}
template<class T1,class T2>
T1 Max(T1 a,T2 b){
cout<<"TemplateMax2"<<endl;
return 0;
}
double Max(double a,double b){
cout<<"MyMax"<<endl;
return 0;
}
int main(){
int i=4,j=5;
Max(1.2,3.4);
Max(i,j);
Max(1.2,3);
}
匹配模板时,不进行类型自动转换
template<class T>
T myfunction(T arg1,T arg2){…………}
int main(){
myfunction(5,7);//通过
myfunction(5.8,8.4);//通过
myfunction(5,8.4);//报错
}
函数模板实例Map:
#include<iostream>
using namespace std;
template<class T,class Pred>
void Map(T s,T e,T x,Pred op){
for(;s!=e;++s,++x)
*x=op(*s);
}
int Cube(int x){return x*x*x;
}
double Square(double x){return x*x;
}
int a[5]={1,2,3,4,5},b[5];
double d[5]={1.1,2.1,3.1,4.1,5.1},c[5];
int main(){
Map(a,a+5,b,Square);
for(int i=0;i<5;++i) cout<<b[i]<<",";
cout<<endl;
Map(a,a+5,b,Cube);
for(int i=0;i<5;++i) cout<<b[i]<<",";
cout<<endl;
Map(d,d+5,c,Square);
for(int i=0;i<5;++i) cout<<c[i]<<",";
cout<<endl;
Map(d,d+5,c,Cube);
for(int i=0;i<5;++i) cout<<c[i]<<",";
cout<<endl;
}
二、类模板
目的:为了多快好省地定义一批相似的类。
类似数组是一种数据类型但是元素可以有不同的类型。
类模板:
template<typename 类型参数1,tyoename 类型参数2…………>
class 类模板名{成员函数和成员变量}
成员函数:
template<class T1,class T2…………>
返回值类型 类模板名 <类型参数名列表>::成员函数名(参数表){…………}
定义对象:
类模板名<真实类型参数表>对象名(构造函数实参表)
由模板实例化所得叫模板类
pair类模板:
#include<iostream>
using namespace std;
template<class T1,class T2>
class Pair{
public:
T1 key;//关键字
T2 value;//值
Pair(T1 k,T2 v) :key(k),value(v){ }
bool operator < (const Pair <T1,T2> & p) const;
};
template<class T1,class T2>
bool Pair <T1,T2>::operator < (const Pair <T1,T2> & p) const{
return key<p.key;
}
int main(){
Pair<string,int> student("Tom",19);//实例化
cout<<student.key<<" "<<student.value;
return 0;
}
函数模板作为类模板成员
#include<iostream>
using namespace std;
template<class T>
class A{
public:
template<class T2>
void Func (T2 t){cout<<t;}
};
int main(){
A<int>a;
a.Func('K');
a.Func("Hello");
return 0;
}
类模板与非类型参数
<类型参数表>出现非类型参数
template<class T,int size>
class CArray{
T array[size];
public:
void Print()
{
for(int i=0;i<size;++i)
cout<<array[i]<<endl;
}
};
CArray<double,40>a2;
CArray<int ,50>a3;//a2,a3不同
1.类模板派生类模型
#include<iostream>
using namespace std;
template<class T1,class T2>
class A{
T1 v1;
T2 v2;
};
template<class T1,class T2>
class B:public A<T2,T1>{
T1 v3;
T2 v4;
};
template<class T>
class C:public B<T,T>{
T v5;
};
int main(){
B<int,double> obj1;
C<int> obj2;
return 0;
}
2.模板类派生类模板
#include<iostream>
using namespace std;
template<class T1,class T2>
class A{
T1 v1;
T2 v2;
};
template<class T>
class B:public A<int ,double>{
T v;
};
int main(){
B<char> obj1;//生成<int,double>是基类
return 0;
}
3.普通类派生类模板
#include<iostream>
using namespace std;
class A{
int v1;
};
template<class T>
class B:public A{
T v;
};
int main(){
B<char> obj1;//生成<int,double>是基类
return 0;
}
4.模板类派生普通类
#include<iostream>
using namespace std;
template<class T>
class A{
T v1;
int n;
};
class B:public A<int>{
double v;
};
int main(){
B obj1;
return 0;
}
类模板与友元
①类模板友元是函数、类、类的成员函数
void Func1(){}
class A{};
class B{
public: void Func(){ }
};
template<class T>
class Tmp1{
friend void Func();
friend class A;
friend void B::Func();
};
②类模板友元是函数模板
#include<string>
#include<iostream>
using namespace std;
template<class T1,class T2>
class Pair{
private:
T1 key;
T2 value;
public:
Pair (T1 k,T2 v):key(k) value(v){};
bool operator < (const Pair <T1,T2> & p)const;
template <class T3,class T4>
friend ostream & operator<< (ostream & o, const Pair<T3,T4> & P);
};
③类的友元是函数模板
template<class T1,class T2》
bool Pair <T1,T2>::operator<(const Pair <T1,T2 & p)const{
return key<p.key;
}
template<class T1,class T2>
ostream & operator <<(ostream & o, const Pair <T1,T2>& p)
{
o<<"("<<","<<p.value<<")";
return 0;
}
④类模板友元是类模板
#include<iostream>
using namespace std;
template<class T>
class B{
T v;
public:
B(T n):v(n){}
template <class T2>
friend class A;
};
template <class T2>
class A {
public:
void Func(){
B<int> o(10);
cout<<o.v<<endl;
}
};
int main(){
A<double>a;
a.Func();
return 0;
}
类模板与静态成员
(模板类中均有该静态成员)静态成员变量需要额外声明
#include<iostream>
using namespace std;
template<class T>
class A{
private:
static int count;
public:
A(){count++;}
~A(){count--;}
A(A &){count++;}
static void PrintCount(){cout<<count<<endl;}
};
template <>int A<int>::count=0;
template <>int A<double>::count=0;
int main(){
A<int> ia;
A<double> da;
ia.PrintCount();
da.PrintCount();
return 0;
}