zoukankan      html  css  js  c++  java
  • 函数模板

    --------------------siwuxie095

       

       

       

       

       

       

       

       

       

    函数模板

       

       

    这里介绍 函数模板,那么为什么要用函数模板呢?

       

       

       

       

    看如下实例:

       

       

       

    当要写一个比较大小的函数并返回较大的值时:

       

    1)如果要比较两个 int 类型的值,就写成第一个函数的形式

    2)如果要比较两个 float 类型的值,就写成第二个函数的形式

    3)如果要比较两个 char 类型的值,就写成第三个函数的形式

       

       

    三个函数除了数据类型有所不同之外,它们的运算逻辑是完全相同的,

    在这种情况下,如果我们要写上这三个函数,简直是太痛苦了,而且

    做的工作也没有意义和价值

       

       

       

    最好是能够有一种方案,即 将类型作为参数传递进去,通过计算机

    自动生成这三个函数,分别处理 int 类型、float 类型、char 类型的

    数据,并能根据传入的数据类型做相应的处理,取得相应的返回值

       

       

       

       

    如果想这么做,我们需要三个关键字:templatetypenameclass

       

    其中:

       

    template,即 模板;而 typename 和 class 所起的作用是相同的

       

    注意:这里的 class 不是用来定义类的,而是用来表明数据类型的

       

       

       

    通过 class 来定义一个函数的模板:

       

       

       

    当要定义函数模板时,需要通过 template 关键字来声明一个

    函数模板,通过 class 或 typename 关键字来声明一个参数,

    该参数能表明一种数据类型

       

    在写 max() 函数时,返回值写上 T,参数用 T 来作参数类型,

    而内部的逻辑不变

       

    如果未来要传入的是 int 类型的数据,计算机就会通过函数模板

    实例化出一个模板函数,即 T 全部被 int 取代,就能处理 int 类

    型的数据了。如果未来要传入的是 float 类型的数据,同理 …

       

       

       

    在具体使用时:

       

       

       

    当使用 max() 比较两个数据大小时,如果不指定数据类型 T,

    计算机会根据自己的判断选择一种模板函数,选择之后就会

    有自己的计算逻辑,如:int ival=max(100,99);,其中 100

    和 99 都是 int 类型的,就会自动实例化一个 int 类型的模板

    函数,然后对 100 99 进行处理,并将 100 返回出来,作

    为返回值赋值给 ival

       

    如果指定了数据类型,如:char cval=max<char>('A','B');

    在函数名后面用一对尖括号括起来,其中写明数据类型,就

    指定传入的参数一定要是这种数据类型的参数才可以,然后

    将返回值返回回来

       

       

       

    函数模板 是函数的模具,通过模子就能一个一个的生产出

    所谓的函数,也就是 模板函数

       

    在计算机中,如果仅仅写出了函数模板而没有使用它,计算机

    是不会产生任何代码数据的,因为它也不知道要产生什么样的

    代码数据

       

    只有当使用函数模板时,计算机才知道具体要实例化出一个怎

    样的模板函数,此时,才会产生真正的代码,参与逻辑的运行

       

       

       

       

    通过 typename 来定义函数的模板:

       

       

       

    swap() 是一个数据交换的函数,所使用的关键字除了 template 就是

    typename,在使用上也没有什么不同,调用 swap(),这里指定的类

    型是 int,即 T 全部被 int 取代,那么传入的参数也必须是 int 类型的,

    才能够处理

       

       

       

       

       

       

    变量作为模板参数

       

       

    看如下实例:

       

       

       

    通过 template 关键字声明一个函数模板,这时,所传入的不再是类型,

    而是个变量,该变量在真正去使用时,才会将函数模板实例化成一个模

    板函数,它才是一个确定的值。如果不使用该函数模板,仍然没有任何

    代码产生

       

    使用时,传入的就不再是一个类型,而是一个确定的值,如:display<10>();

    此时这个值其实就是一个常数,只不过在函数模板中体现出来的,看上去像是

    一个变量,真正编译出来就是一个常数

       

       

       

       

       

       

    多参数函数模板

       

       

    模板有时会变的很复杂,因为我们不能确定在日常应用中,只有

    一个类型作为模板的参数,如果有多个参数该如何处理呢?

       

       

    看如下实例:

       

       

    当有多个参数时,需要用逗号隔开,两个 typename 都不能省略,

    此时,T 和 C 都变成了函数模板的参数,在使用时,需要将 T 和

    C 的类型都指定出来,如:display<int,string>(a,str);

       

       

       

    typename 和 class 所起的作用是一样的,所以在使用时,可以

    混用,如下:

       

       

       

       

    还可以这样来混用:typename 来定义数据类型 T,另外一个则是

    变量 size,在使用时就可以指定 T 的数据类型和 size 的值,如下:

       

       

       

       

       

       

       

    函数模板与重载

       

       

    函数模板看上去就已经是一个重载的关系了,因为:通过函数模板

    可以拓出无数个模板函数,我们可以尽情的去想象它能拓出的数据

    类型,这些模板函数之间就形成了一种重载

       

    此外, 不同的函数模板所拓出的模板函数,也可能形成重载

       

    看如下实例:

       

     

       

    当前这三个函数模板,其实都有所不同,第一个函数模板只有 1 个参数,

    第二个函数模板有两个参数,这就是参数的个数不同。第三个函数模板

    也只有一个参数,看上去和第一个函数模板是一样的,但是第三个函数

    模板的模板参数本身就有两个

       

       

       

    在使用时:

       

       

       

    通过三个不同的函数模板可以实例化出三个不同的模板函数,它们

    之间就形成了重载

       

    注意:当定义出函数模板时,函数模板本身并不是互相重载的关系,

    因为在内存中,仅仅是将函数模板定义出来,并不能在内存中产生

    出任何代码

       

    只有在使用时,编译器才会产生相应的函数代码,产生函数代码后,

    这些函数代码彼此之间才称得上是重载关系

       

       

       

       

    程序:

       

    main.cpp:

       

    #include "stdlib.h"

    #include <iostream>

    using namespace std;

       

       

    //template关键字声明一个模板 T是模板类型 也是模板参数

    template<typename T>

    //此即为函数模板 如果仅仅只是写出函数模板 而没有使用它

    //那么计算机是不会产生任何代码数据的 因为它也不知道要产生什么样的代码数据

    void display(T a)

    {

    cout << a << endl;

    }

       

    //使用了不同的关键字 但意义一样(所起作用一样)可以混用

    //推荐使用typename 毕竟class是类的关键字

    template<typename T,class S>

    void display(T t, S s)

    {

    cout << t << endl;

    cout << s << endl;

    }

       

       

    //这里变量作为了模板参数 KSize 此时传入的既有类型参数 又有变量参数

    template<typename T,int KSize>

    void display(T t)

    {

    for (int i = 0; i < KSize;i++)

    {

    cout << t << endl;

    }

    }

    int main(void)

    {

    //此即为模板函数:通过函数模板生产出来的函数 也即实例化

    //这时计算机才会产生真正的代码 才会参与逻辑运行

    display<char>('Q');

    display<int, double>(5, 10.89);

    display<int, 5>(9);

    system("pause");

    return 0;

    }

       

    //同一函数模板生产出来的模板函数互为重载

    //不同函数模板生产出来的模板函数也有可能互为重载

    //

    //在定义出函数模板的时候 函数模板本身并不是互相重载的关系

    //因为在内存当中我们仅仅将函数模板定义出来 并不能在内存中产生出任何的代码

    //

    //只有在使用它们的时候 编译器才会为我们产生出相应的函数代码来

    //这些函数代码彼此间才称得上互为重载关系

       

       

       

       

       

       

       

       

       

    【made by siwuxie095】

  • 相关阅读:
    js 延迟函数
    reduce
    angular2 select 联动
    小程序图片展示模式
    e.target 和 e.currentTarget
    jquery weui 图片浏览器Photo Browser
    ng2中 如何使用自定义属性data-id 以及赋值和取值操作
    jquery img src赋值
    JQuery 自定义属性取值 赋值
    unsupported media type 415
  • 原文地址:https://www.cnblogs.com/siwuxie095/p/6817183.html
Copyright © 2011-2022 走看看