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

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

2016-05-13 10:59 351 查看
一、函数模板

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后含有< > 而显示实例化没有

综上:我们见识了隐式实例化,显示实例化和显示具体化。他们都被成为具体化。

他们的相同之处在于,他们表示的都是使用具体类型的函数定义,而不是通用描述。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c++ 模板