C++模板(一) ----函数模板
2016-05-13 10:59
351 查看
一、函数模板
1、先看一个简单的模板函数定义
这里继续给出调用代码:
2、模板函数的重载
需要多个不同的类型使用同一种算法时,可使用模板。然而,并非所有的类型都使用相同的算法,为了满足需求,可以像重载常规函数定义那样重载模板定义。
重载模板函数代码如下:
第二个函数作用是交换数组。继续给出函数的调用,以及显示函数show();
3、模板的局限性
通过上述代码我们可以看到,模板函数可能会遇到无法处理的某些类型。比如我们不同通过第一个模板函数用来交换数组。再比如,我们不能为一些结构或者类来使用=号进行交换(如果没有重写赋值运算符符的话)。这里c++提供2中解决方案:
第一种:重载运算符,第二种:显示具体化。
4、显示具体化
c++98标准选择了下面的方法:
对于给定的函数名,可以有非模板函数、模板函数和显示模板函数以及他们的重载版本。
显示具体化的原型和定义应以template<>打头,并通过名称来指出类型。
具体化优先于常规模板,而非模板优先于具体化和常规模板。
假设有结构体
给出非模板函数、模板函数、具体化模板函数的声明:
这里具体化模板函数中的< job >是可选的,因为参数列表中已有类型的声明。即可以也可以写作:template<> void Swap(job &, job &);
附上测试代码:
5、实例化
在代码中包含函数模板本身并不会生成函数定义,它只是一个用于生成函数定义的方案。模板并非函数定义。
c++中有2种模板函数实例化。第一种是隐式实例化(最常用的一种),第二种为显示实例化。
隐式实例化就是,我们上文中用到调用时用到的那样:
这就是隐式实例化,他最终生成了一个 函数定义他的参数类型为int型。即:void Swap(int i,int j){}
显示实例化则需要用 <> 指示出类型 并在声明前加上关键字 template。
注意显示具体化声明在关键字template后含有< > 而显示实例化没有
综上:我们见识了隐式实例化,显示实例化和显示具体化。他们都被成为具体化。
他们的相同之处在于,他们表示的都是使用具体类型的函数定义,而不是通用描述。
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++实现JNI接口需要注意的事项
- 关于指针的一些事情
- 设计模式之行为型模式 - 调用行为的传递问题
- [div+css]晒晒最新制作专题推广页模板
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- 2008大学生入党申请书 模板
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- IMAIL多语言模板两套Outlook&Gmail模板下载
- C++联合体转换成C#结构的实现方法
- C++高级程序员成长之路
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- C++变位词问题分析
- C/C++数据对齐详细解析
- C++基于栈实现铁轨问题
- C++中引用的使用总结
- 使用Lua来扩展C++程序的方法