您的位置:首页 > 编程语言 > C语言/C++

C++深入理解(4)------函数模板以及显式具体化(读书笔记)

2018-02-26 14:57 686 查看
    在编程的过程中虽然很少使用到函数模板,但是在底层代码的编写中却有时会用到,下面将详细介绍一下函数模板:
    函数模板是一种应用泛型的一种方式,可以定义一个函数,函数的参数和返回值都是可以根据模板而变动的,不用定义多个重载函数来实现因为参数不同而功能相同的问题。
    如下面的交换函数,void swap(int &a,int &b){}; 有时候我们会用到int类型,有时候会用到double类型,功能相同的函数却因为参数不同却要重新编写一次,不仅浪费时间,而且非常容易出错,所以使用函数模板就可以避免这种问题。

    下面写出模板定义的标准格式
    template <typename T>void swap(T &a,T &b){}或者

    template<class T> void swap(T &a,T &b);
    这里简单的说下tpyename和class的异同:他们两个在作用上是相同的,都是表示模板类型的关键词,两者在使用上没有任何区别,唯一的区别在与typename可以更清晰的告诉读者是模板类型,而class更绕一点,但是有大量的库使用class这种用法的。

    本质上说:模板并不创建任何函数,而是类似一个过程语言,它来告诉编译器怎么去创建一个函数,如需要用int来替换时,就会用int来创建一个函数,而需要用double来替换时,就用double来创建一个函数。因此函数模板并不能缩短函数执行过程, 在执行时仍然需要创建两个函数定义,而最终的代码是不包含任何模板的,只包含模板生成的实际函数。所以使用模板的好处是可以减少手工定义的工作量。

    这里额外还要说的一个概念是显式具体化,有时候定义的模板能处理大部分的类型,但是有某些特殊类型需要却与基本的算法不同,这时就要用到显式具体化这种神奇的东西:

    其标准的格式是:

    template <> void swap<job>(job &a,job &b){.......};
    这样可以定义复杂的结构job,当调用以job作为参数的函数时,就优先调用这个显示具体化的函数,如果没有job作为参数的显式具体化,那么还是根据老的模板来定义job函数。

    这里需要另外说明的还有一个概念:显式实例化。这个概念比较和显示具体化是两个不同的概念。显示实例化的标准格式 template void swap<int>(int &a,int &b);

    通过使用显示实例化这样声明,编译器就知道要穿件一个int类型的函数定义,与之对应的是隐式实例化,只有当遇到swap(a,b),a,b都为int类型时才会创建这个函数定义。而显示实例化却是要穿件另外一种类型的不同算法,前者(显示实例化)是不改变算法只创建函数,而后者则是即改变算法也创建。
    概念基本讲完了,说下使用中注意的细节,在使用中常常会遇到这样的问题:

    swap(T1 &a, T2 &b){    ...   ?type? = a + b; ...} 那么a+b是什么类型呢,因为a可能是int,b可能是double,则a+b为double,其他传入类型又是不同的,这里C++增加了一个关键词decltype,具体使用为decltype(a+b) c=a+b;decltype() 后声明的变量c为与()内部的变量是同一种类型的变量。
    还有一种返回值也是不知道type的,如?type? swap(T a,T b);返回值也是不定的,这里可以使用C++新的后置返回类型,具体的格式如下:

    template <class T1,class T2>

    auto func(T1 x,T2)->decltpye(x+y){}
    其中的->表示返回值类型为->后类型相同的类型。

    
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  函数模板