1 泛型程序设计:使用模板的程序设计
2 考虑问题:能否只写一个Swap就能交换各种类型的变量?
交换两个整形变量的值的Swap函数
void Swap(int& x, int& y)
{
int tmp = x; x = y; y = tmp;
}
交换两个double型变量的值的Swap函数
void Swap(double& x, double& y)
{
double tmp = x; x = y; y = tmp;
}
解决方案:函数模板
通用格式:
template <class 类型参数1, class 类型参数2, ......>
返回值类型 模板名(形参表)
{
函数体
};
eg:
template <class T>
void Swap(T& x, T& y)
{
T tmp = x; x = y; y = tmp;
}
int main()
{
int n = 1, m = 2;
Swap(n, m); //编译器自动生成 void Swap(int&, int&)函数
double f = 1.2, g = 2.3;
Swap(f, g); // 编译器自动生成 void Swap(double&, double&)函数
return 0;
}
3 函数模板中可以有不止一个类型参数
template <class T1, class T2>
T2 print(T1 arg1, T2 arg2)
{
cout << arg1 << " " << arg2 << endl;
return arg2;
}
4 求数组最大元素的MaxElement函数模板见本工程(maxValueTemplate.cpp)
/**
* 求数组最大元素的MaxElement函数模板
*/
#include <iostream>
using namespace std;
template <class T>
T MaxElement(T a[], int size) // size是数组元素个数
{
T tmpMax = a[0];
for(int i = 1; i < size; ++i)
if(tmpMax < a[i])
tmpMax = a[i];
return tmpMax;
}
int main()
{
}
5 编译器从模板生成函数的过程称为模板的实例化,编译器编译到一条调用模板语句的时候就会模板实例化。
所谓模板实例化就是将模板中的类型换成具体的类型,得到一个函数
6 不通过参数实例化函数模板(见本工程 templatesample.cpp)
/**
* 函数模板 不通过参数实例化函数模板
*/
#include <iostream>
using namespace std;
template <class T>
T Inc(T n)
{
return 1 + n;
}
int main()
{
// 不通过参数实例化函数模板 Inc<double>
cout << Inc<double>(4)/2;
return 0;
}
7 函数模板的重载
函数模板可以重载,只要它们的形参表或类型参数表不同即可。
template <class T1, class T2> // 类型参数表
void print(T1 arg1, T2 arg2) // 形参表
{
cout << arg1 << " " << arg2 << endl;
}
template <class T>
void print(T arg1, T arg2)
{
cout << arg1 << " " << arg2 << endl;
}
template <class T, class T2>
void print(T arg1, T arg2)
{
cout << arg1 << " " << arg2 << endl;
}
8 函数模板和函数的次序
在有多个函数和函数模板名字相同的情况下,编译器如下处理一条函数调用语句
1)先找参数完全匹配的普通函数(非由模板实例化而得到的函数)
2)再找参数完全匹配的模板函数
3)再找实参数经过自动类型转换后能够匹配的普通函数
4)上面的都找不到,则报错
eg(见本工程funcTemplateSort.cpp)
/**
* 演示函数模板和函数的次序
*/
#include <iostream>
using namespace std;
template <class T>
T Max(T a, T b)
{
cout << "TemplateMax" << endl;
return 0;
}
template <class T, class T2>
T Max(T a, T2 b)
{
cout << "TemplateMax2" << endl;
return 0;
}
double Max(double a, double b)
{
cout << "MyMax" << endl;
return 0;
}
int main()
{
int i = 4, j = 5;
Max(1.2, 3.4);
Max(i, j);
Max(1.2, 3);
return 0;
}
9 匹配模板函数时,不进行类型自动转换
template <class T>
T myFunction(T arg1, T arg2)
{
cout << arg1 << " " << arg2 << "\n";
return arg1;
}
myFunction(5, 7); // ok replace T with int
myFunction(5.8 8.4); // ok replace T with double
myFunction(5, 8.4); // error, no matching function for call to 'myFunction(int , double)'
10 函数模板实例:Map (见本工程funcTemplateMap.cpp)
/**
* 函数模板实例 Map
*/
#include <iostream>
using namespace std;
template <class T, class Pred>
// Map可以完成的一项功能 把一个区间 区间起点为s 区间终点为e 终点不包含在内,吧区间中的每一个元素,通过op函数做一个变换,变换后的结果拷贝到目标区间,目标区间起点为x
void Map(T s, T e, T x, Pred op)
{
for(; s != e; ++s, ++x)
*x = op(*s);
}
int Cube(int x) // 返回x的3次方
{
return x * x * x;
}
double Square(double x) // 返回x的平方
{
return x * x;
}
int a[5] = {1, 2, 3, 4, 5},b[5];
double d[5] = {1.1, 2.1, 3.1, 4.1, 5.1}, c[5];
int main()
{
/**
*
* Map(a, a+5, b, Square); //实例化出以下函数
* void Map(int* s, int* e, int* x, double (*op)(double)) // op代表一个函数指针
* {
* for(: s != e; ++s, ++x)
* *x = op(*s);
* }
* 函数的名字跟函数指针这种类型能够匹配
*/
Map(a, a+5, b, Square);
for(int i = 0; i < 5; ++i)
cout << b[i] << ",";
cout << endl;
Map(a, a+5, b, Cube);
for(int i = 0; i< 5; ++i)
cout << b[i] << ",";
cout << endl;
Map(d, d+5, c, Square);
for(int i = 0; i < 5; ++i)
cout << c[i] << ",";
cout << endl;
return 0;
}