C++模板(一) ----函数模板

一、函数模板
1、先看一个简单的模板函数定义

/*
 *在标准c++98添加typename关键字之前,使用class 来创建模板,之后用typename 替代了class
 * c++98 之前的模板定义定义为: template < class AnyType> void fun(){...}
 */
template <typename AnyType>
void Swap(AnyType &a, AnyType &b) {
    AnyType temp;
    temp = a;
    a = b;
    b = temp;
    return;
}

这里继续给出调用代码:

int main()
{
    int a = 10, b = 20;
    double c = 10.1, d = 10.2;
    Swap(a, b);
    Swap(c, d);
    std::cout << "a = " << a << " b=" << b<< std::endl;
    std::cout << "c = " << c << " d=" << d << std::endl;
    system("pause");
    return 0;
}
执行结果:
a = 20 b=10
c = 10.2 d=10.1
请按任意键继续. . .

2、模板函数的重载
需要多个不同的类型使用同一种算法时,可使用模板。然而,并非所有的类型都使用相同的算法,为了满足需求,可以像重载常规函数定义那样重载模板定义。
重载模板函数代码如下:

template <typename AnyType>
void Swap(AnyType &a, AnyType &b) {
    AnyType temp;
    temp = a;
    a = b;
    b = temp;
    return;
}

template <typename AnyType >
void Swap(AnyType *a, AnyType *b,int n) {
    AnyType  temp;
    for (int i = 0; i < n; i++) {
        temp = a[i];
        a[i] = b[i];
        b[i] = temp;
    }
    return;
}

第二个函数作用是交换数组。继续给出函数的调用,以及显示函数show();


/*用来显示数组内容*/
template <typename AnyType>
void Show(AnyType *a, int n) {
    for (int i = 0; i < n; i++) {
        std::cout << " " << a[i];
    }
    std::cout << std::endl;
}
int main()
{
    int a = 10, b = 20;
    double c = 10.1, d = 10.2;

    int aa[5] = { 0,1,2,3,4 };
    int bb[5] = { 4,3,2,1,0 };
    Swap(a, b);
    Swap(c, d);
    Swap(aa, bb,5);

    std::cout << "a = " << a << " b=" << b<< std::endl;
    std::cout << "c = " << c << " d=" << d << std::endl;
    std:: cout << "aa = ";
    Show(aa, 5);
    std::cout << "bb =";
    Show(bb, 5);
    system("pause");
    return 0;
}
执行结果:
a = 20 b=10
c = 10.2 d=10.1
aa =  4 3 2 1 0
bb = 0 1 2 3 4
请按任意键继续. . .

3、模板的局限性
通过上述代码我们可以看到,模板函数可能会遇到无法处理的某些类型。比如我们不同通过第一个模板函数用来交换数组。再比如,我们不能为一些结构或者类来使用=号进行交换(如果没有重写赋值运算符符的话)。这里c++提供2中解决方案:
第一种:重载运算符,第二种:显示具体化。
4、显示具体化
c++98标准选择了下面的方法:

  • 对于给定的函数名,可以有非模板函数、模板函数和显示模板函数以及他们的重载版本。
  • 显示具体化的原型和定义应以template<>打头,并通过名称来指出类型。
  • 具体化优先于常规模板,而非模板优先于具体化和常规模板。
    假设有结构体
    struct job
    {
    char name[40];
    double salary;
    int floor;
    };

给出非模板函数、模板函数、具体化模板函数的声明:

/*非模板函数*/
void Swap(job &, job &);
/*常规模板函数*/
template <typename T>
void Swap(T &, T &);
/*具体化模板函数*/
template<> void Swap<job>(job &, job &);

这里具体化模板函数中的< job >是可选的,因为参数列表中已有类型的声明。即可以也可以写作:template<> void Swap(job &, job &);
附上测试代码:

#include "stdafx.h"
#include <iostream>
struct job
{
    char name[40];
    double salary;
    int floor;
};

/*常规模板函数*/
template <typename T>
void Swap(T &, T &);
/*具体化模板函数*/
template<> void Swap<job>(job &, job &);

void Show(job & j);
int main() {
    using namespace std;
    cout.precision(2);
    cout.setf(ios::fixed, ios::floatfield);
    int i = 10, j = 20;
    cout << " i,j =  " << i << " , " << j << " . \n";
    cout << " 使用 template <typename T> void Swap(T & ,T &) 函数" << endl;
    Swap(i, j);
    cout << " Now i,j = " << i << " ," << j << ". \n";

    job sue = { "Susan Yaffee",7300.60,7 };
    job sindney = { "Sidney Tafee",78060.72,9 };
    cout << "Before job swapping : \n";
    Show(sue);
    Show(sindney);
    Swap(sue, sindney);
    cout << " after job swapping: \n";
    Show(sue);
    Show(sindney);
    system("pause");
    return  0;

}
/*常规模板函数*/
template <typename T>
void Swap(T & a, T & b) {
    T temp;
    temp = a;
    a = b;
    b = temp;
}
/*
*具体化模板函数
*这个函数值交换job中的 salary 和 floor
*/
template<> void Swap<job>(job & a, job & b) {
    double t1;
    int t2;

    t1 = a.salary;
    a.salary = b.salary;
    b.salary = t1;

    t2 = a.floor;
    a.floor = b.floor;
    b.floor = t2;
}

void Show(job & j) {
    using namespace std;
    std::cout << j.name << " : $" << j.salary << " on floor " << j.floor << endl;
}

执行结果:
 i,j =  10 , 20 .
 使用 template <typename T> void Swap(T & ,T &) 函数
 Now i,j = 20 ,10.
Before job swapping :
Susan Yaffee : $7300.60 on floor 7
Sidney Tafee : $78060.72 on floor 9
 after job swapping:
Susan Yaffee : $78060.72 on floor 9
Sidney Tafee : $7300.60 on floor 7
请按任意键继续. . .

5、实例化
在代码中包含函数模板本身并不会生成函数定义,它只是一个用于生成函数定义的方案。模板并非函数定义。
c++中有2种模板函数实例化。第一种是隐式实例化(最常用的一种),第二种为显示实例化。
隐式实例化就是,我们上文中用到调用时用到的那样:

int i = 10, j = 20;
    Swap(i, j);

这就是隐式实例化,他最终生成了一个 函数定义他的参数类型为int型。即:void Swap(int i,int j){}
显示实例化则需要用 <> 指示出类型 并在声明前加上关键字 template。

//显示实例化
template void Swap<int>(int &, int &);

注意显示具体化声明在关键字template后含有< > 而显示实例化没有

综上:我们见识了隐式实例化,显示实例化和显示具体化。他们都被成为具体化。
他们的相同之处在于,他们表示的都是使用具体类型的函数定义,而不是通用描述。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值