C++ 泛型编程(GP)函数模板

目录

1提出背景

2函数模板(语法规则)

3调用方式

3.1隐式调用

3.2显示调用

4和普通函数的区别

5函数模板的限制

6举例


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等等。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值