c++复习之 函数模板template(10)

函数模板template

函数模板是通用的函数描述,它们使用泛型来定义函数,其中的泛型可用具体的类型(如int和double)替换。通过将类型作为参数传递给模板,可使编译器生成该类型的函数。这种编程方式也叫做通用编程。由于类型是用参数表示的,因此模板特性有时也被称为参数化类型。
参数模板允许以任意类型的方式来定义函数。例如,可以这样建立一个交换模板:

template<typename Anytype>//或者 template<class Anytype>
void Swap(Anytype &a, Anytype &b)
{
    Anytype temp;
    temp = a;
    a = b;
    b = temp;
}

第一行指出,要建立一个模板,并将类型命名为Anytype。关键字template和typename是必需的,除非可以使用关键字class替代typename。例外,必须使用尖括号<>。类型名可以任意选择(T?)。模板不创建任何函数,只是告诉编译器如何定义函数。需要交换int的函数时,编译器将按模板模式创建这样的函数,并用int代替Anytype。
使用模板函数时,在文件的开始位置提供模板函数的原型,并在main()后面提供模板函数的定义。

#include <iostream>
template<typename T>
void Swap(T &a, T &b);

int main()
{
    using namespace std;
    int i = 10;
    int j = 20;
    Swap(i, j);

    double x = 12.2;
    double y = 34.6;
    Swap(x, y);

    getchar();
    return 0;
}

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

运行上述程序后,编译器最终将生成两个独立的函数定义(即不是内联的,和普通函数的声明定义相同),就像手工定义了这些函数一样,最终的代码不包括任何模板,只包含了为程序生成的实际函数。

1 重载的模板

可以像重载常规函数定义那样重载模板定义,被重载的模板的函数特征标必须不同。

template <typename T>
void Swap(T &a, T &b);

template <typename T>
void Swap(T *a, T *b, int n);//模板的函数特征标所有不同,在结构上不同才可以

并非所有的模板参数都必须是模板参数类型,int n就不是模板参数类型。

2 模板的局限性

编写的模板可能无法处理某些类型。

3 显式具体化

C++98有如下的方法:

  • 对于给定的函数名,可以有非模板函数、模板函数和显式具体化模板函数以及它们的重载版本。
  • 显式具体化的原型和定义应以template<>打头,并通过名称来指出类型。
  • 具体化优先于常规模板,而非模板函数优先于具体化和常规模板。

“` c++
//non template function prototypr
void Swap(job &, job &);
//template prototype
template
void Swap(T &a, T &b);
//explicit specialization for the job type
template<>void Swap(job &a, job &b);

4 实例化和具体化

在代码中包含函数模板本身并不会生成函数定义,它只是一个用于生成函数定义的方案。编译器使用模板为特定类型生成函数定义时,得到的是模板实例(instantiation)。模板并非函数定义,但使用int的模板实例是函数定义。这种实例化方式被称为隐式实例化(implicit instantiation)。
c++允许显式实例化,直接命令编译器创建特定的实例。

template void Swap<int>(int &, int &);

隐式实例化、显式实例化和显式具体化统称为具体化(specialization),相同之处在于都是使用具体类型的函数定义,而不是通用描述。

5 编译器选择使用哪个函数版本

猜你喜欢

转载自blog.csdn.net/sangohan77/article/details/79446248