目录
1提出背景
void myIntSwap(int a,int b){
int temp = a;
a = b;
b = temp;
}
void myDoubleSwap(double a,double b){
double temp = a;
a = b;
b = temp;
}
为了提高代码的复用性,针对上述形式的代码,可以使用函数模板
template<class T>
void Widget::printItem(T arr[],int len){
for(int i = 0;i<len;++i){
std::cout<<arr[i]<<" ";
}
}
template<class T1,class T2,class T3>
void Widget::testForTemplate(T1 a1,T2 a2,T3 a3){
qDebug()<<a1;
qDebug()<<a2;
qDebug()<<a3;
}
进行重构
2函数模板(语法规则)
template<class T1,class T2,...>
返回值 函数名(T1 参数名,T2 参数名,...){
//函数实体...
}
其中T1,T2均为抽象类型的名称。
注意,template的作用域只限制于紧跟着template的函数,如果多个函数都需要使用模板,那么需要在每个函数的实现部分之前,增加template关键字,来进行作用域的声明。
如果声明和实现是分开的,那么声明和实现部分的前面都需要有template关键字,用以声明抽象类型的作用域。
template<class T>
void Widget::printItem(T arr[],int len){
for(int i = 0;i<len;++i){
std::cout<<arr[i]<<" ";
}
}
template<class T1,class T2,class T3>
void Widget::testForTemplate(T1 a1,T2 a2,T3 a3){
qDebug()<<a1;
qDebug()<<a2;
qDebug()<<a3;
}
3调用方式
3.1隐式调用:
不明确指定参数的类型,传参的时候进行自行推到。
qDebug()<<endl;
qDebug()<<"隐式调用";
qDebug()<<"int double double";
testForTemplate(1,2.2,3.3);
qDebug()<<"string int char";
testForTemplate("123",2,'a');
qDebug()<<endl;
3.2显示调用:
调用格式:
函数名<各个参数的具体类型,...>(arg1,arg2,arg3,...)
qDebug()<<"显式调用";
testForTemplate<int,double,long>(1,2.2,3.3);
4和普通函数的区别
①函数模板不能进行隐式类型的转换
//.h
void myPrint(int arg);
//.cpp
double arg = 2.5;
myPrint(arg);
②if出现重载,优先使用“普通函数”,如果想强制调用“函数模板”,使用空参数列表
myPrint<>(a,b);
③函数模板也可以发生重载
5函数模板的限制
①编译器并不是把函数模板 转化为 成能处理任何数据类型的函数,比如自定义类型是无法处理的。
class Person{
int id;
int age;
string name;
};
现在有一个自定义类型,Person。
如果我想使用下面的函数模板:
template<class T>
bool myJudge(T a,T b){
return a == b;
}
显然,如果传入参数的类型是Person,那么显然没办法执行,下面我们通过具体化自定义类型,解决上述问题。
//函数模板
template<> bool myJudge<Person>(Person & a,Person & b){
return a.age == b.age;
}
②函数模板通过具体类型产生
编译器会对函数模板进行两次编译,在声明的地方对模板代码本身进行编译,在调用的地方对参数替换后的代码进行编译。
6举例
//.h
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
template<class T>
void sortFunction(T arr[],int len);
template<class T>
void mySort(T arr[],int len);
template<class T>
void mySwap(T & a,T & b);
template<class T>
void printItem(T arr[],int len);
template<class T1,class T2,class T3>
void testForTemplate(T1 a1,T2 a2,T3 a3);
private:
Ui::Widget *ui;
};
//.cpp
template<class T>
void Widget::sortFunction(T arr[],int len){
mySort(arr,len);
printItem(arr,len);
}
template<class T>
void Widget::mySwap(T & a,T & b){
T temp =a;
a = b;
b = temp;
}
template<class T>
void Widget::mySort(T arr[],int len){
for(int i = 0;i<len;++i){
int min = i;
for(int j = i+1;j<len;++j){
if(arr[min] > arr[j]){
min = j;
}
}
if(min != i){
mySwap(arr[min],arr[i]);
}
}
}
template<class T>
void Widget::printItem(T arr[],int len){
for(int i = 0;i<len;++i){
std::cout<<arr[i]<<" ";
}
}
输出:
以上函数,可以对任何数据类型的函数进行排序,不论int,double,char等等。