zoukankan      html  css  js  c++  java
  • C++学习33 函数模板

    在《C++函数重载》一节中,为了求三个数的最大值,我们通过函数重载定义了三个名字相同、参数列表不同的函数,如下所示:

    //求三个整数的最大值
    int max(int a, int b, int c){
        if(b>a) a=b;
        if(c>a) a=c;
        return a;
    }
    //求三个浮点数的最大值
    double max(double a, double b, double c){
        if(b>a) a=b;
        if(c>a) a=c;
        return a;
    }
    //求三个长整型数的最大值
    long max(long a, long b, long c){
        if(b>a) a=b;
        if(c>a) a=c;
        return a;
    }

    这些函数虽然在调用时方便了一些,但从本质上说还是定义了三个功能相同、函数体相同的函数,仍然不够节省代码。能不能把它们压缩成一个呢?

    能!可以借助本节讲的函数模板。

    我们知道,数据或数值可以通过函数参数传递,在函数定义时它们是未知的,只有在发生函数调用时才能确定其值。这就是数据的参数化。

    其实,数据类型也可以通过参数来传递,在函数定义时可以不指明具体的数据类型,当发生函数调用时,编译器可以根据传入的参数自动确定数据类型。这就是数据类型参数化。

    所谓函数模板,实际上是建立一个通用函数,其返回值类型和形参类型不具体指定,用一个虚拟的类型来代替(实际上是用一个标识符来占位)。这个通用函数就称为函数模板(Function Template)。凡是函数体相同的函数都可以用这个模板来代替,不必定义多个函数,只需在模板中定义一次即可。在调用函数时系统会用实参的类型来取代模板中的虚拟类型,从而实现了不同函数的功能。

    定义模板函数的语法为:

    template <typename 数据类型参数 , typename 数据类型参数 , ...> 返回值类型 函数名(形参列表){
        //TODO:
        //在函数体中可以使用数据类型参数
    }

    其中,template 是定义模板函数的关键字,template后面的尖括号不能省略;typename 是声明数据类型参数名的关键字,多个数据类型参数以逗号分隔。例如,求两个数的值:

    //在返回值类型、形参列表、函数体中都可以使用T
    template<typename T> T sum(T a, T b){
        T temp = a + b;
        return temp;
    }

    template<typename T>为模板头,T为类型参数。模板函数的调用形式和普通函数一样:

    int n = sum(10, 20);
    float m = sum(12.6, 23.9);

    编译器可以根据调用时传递的参数来自动推演数据类型。

    改进本节开头的代码,通过函数模板来求三个数的最大值。

    #include <iostream>
    using namespace std;
    template<typename T>  //模板头,这里不能有分号
    T max(T a, T b, T c){ //函数头
        if(b>a) a=b;
        if(c>a) a=c;
        return a;
    }
    int main( ){
        //求三个整数的最大值
        int i1, i2, i3, i_max;
        cin >> i1 >> i2 >> i3;
        i_max = max(i1,i2,i3);
        cout << "i_max=" << i_max << endl;
        //求三个浮点数的最大值
        double d1, d2, d3, d_max;
        cin >> d1 >> d2 >> d3;
        d_max = max(d1,d2,d3);
        cout << "d_max=" << d_max << endl;
        //求三个长整型数的最大值
        long g1, g2, g3, g_max;
        cin >> g1 >> g2 >> g3;
        g_max = max(g1,g2,g3);
        cout << "g_max=" << g_max << endl;
        return 0;
    }

    模板函数也可以提前声明,不过声明时需要带上模板头,请看下面的例子:

    #include <iostream>
    using namespace std;
    //声明模板函数
    template<typename T> T sum(T a, T b);
    int main(){
        cout<<sum(10, 40)<<endl;
        return 0;
    }
    //定义模板函数
    template<typename T> T sum(T a, T b){
        T temp = a + b;
        return temp;
    }

    可以发现,模板头和函数定义(声明)是一个不可分割的整体,可以换行,但是中间不能有分号。

  • 相关阅读:
    Elasticsearch嵌套聚合
    Elasticsearch+Logstash+Kibana教程
    《胡雪岩·灯火楼台》—— 读后总结
    Elasticsearch使用REST API实现全文检索
    Elasticsearch集群配置以及REST API使用
    《Node web开发》笔记
    我的第一个Node web程序
    Spring boot整合shiro权限管理
    SpringBoot 整合Shiro 一指禅
    SpringBoot,用200行代码完成一个一二级分布式缓存
  • 原文地址:https://www.cnblogs.com/Caden-liu8888/p/5835585.html
Copyright © 2011-2022 走看看