一、函数模版
函数模板不是一个实在的函数,编译器不能为其生成可执行代码。定义函数模板后只是一个对函数功能框架的描述,当它具体执行时,将根据传递的实际参数决定其功能。
函数模板类型自推:能够根据参数类型自动推演出模板类型参数。
1、语法格式
template<类型形式参数表>
返回类型 函数名(形式参数表)
{ }
2、函数模板的实例化
编译时期根据模板调用的类型方式,自动生成一份对应于该类型的代码
1)显示实例化:显示实例化也称为外部实例化。在不发生函数调用的时候将函数模板实例化,或者在不使用类模板的时候将类模板实例化称之为模板显示实例化。
2)隐式实例化:函数模板隐式实例化指的是在发生函数调用的时候,如果没有发现相匹配的函数存在,编译器就会寻找同名函数模板,如果可以成功进行参数类型推演,就对函数模板进行实例化。
隐式实例化:
//函数模板
template<typename T>
bool compare(const T a,const T b)
{
cout << "bool compare(T a, T b) " << typeid(T).name() << endl;
return a > b;
}
int main()
{
//隐式实例化
compare(3,4);
return 0;
}
显式实例化:
template<typename T>
bool compare(const T a,const T b)
{
cout << "bool compare(T a, T b) " << typeid(T).name() << endl;
return a > b;
}
//显示实例化
template void compare<int>(const int&,const int&);
3、函数模版的特例化
特例化是实例化一个模板,而非重载它。特例化不影响参数匹配。参数匹配都以最佳匹配为原则。
格式:
template<>
返回类型 函数名<形式参数表>(参数表)
{ }
//函数模板
template<typename T>
bool compare(const T a,const T b)
{
cout << "bool compare(T a, T b) " << typeid(T).name() << endl;
return a > b;
}
//函数模板的特例化
typedef char* CharPtr;
template<>
bool compare<CharPtr>(const CharPtr a, const CharPtr b)
{
cout << "bool compare<const char *>(const char * a,const char* b)" << endl;
return strcmp(a, b) > 0;
}
4、函数模版的重载与非模版函数
1) 函数模板可以像普通函数一样被重载
2) C++编译器优先考虑普通函数
3) 如果函数模板可以产生一个更好的匹配,那么选择模板
4) 可以通过空模板实参列表的语法限定编译器只通过模板匹配
//函数模板
template<typename T>
bool compare(const T a,const T b)
{
cout << "bool compare(T a, T b) " << typeid(T).name() << endl;
return a > b;
}
//函数模板的特例化
template<>
bool compare<CharPtr>(const CharPtr a, const CharPtr b)
{
cout << "bool compare<const char *>(const char * a,const char* b)" << endl;
return strcmp(a, b) > 0;
}
//非模板函数
bool compare(const double a, const double b)
{
cout << "bool compare(const double a, const double b)" << endl;
return a > b;
}
//函数模板的重载
template<typename T>
bool compare(T *arr1,int len1,T *arr2,int len2)
{
cout << "bool compare(T *arr1,int len1,T *arr2,int len2) " << typeid(arr1).name()<<endl;
int i, j;
for ( i = 0, j = 0; i < len1&&j < len2; i++, j++)
{
if (arr1[i] > arr2[j])
{
return true;
}
}
if (i == len1)
{
return false;
}
return true;
}
5、多个形式参数列表的使用
#include<iostream>
using namespace std;
template<typename T>
bool Mygre(T a, T b)
{
return a > b;
}
typedef char * CHARPtr;
template<>
bool Mygre<char *>(const CHARPtr a, const CHARPtr b)
{
return strcmp(a,b) > 0;
}
template<typename T>
bool Myless(T a, T b)
{
return a < b;
}
typedef char * CHARPtr;
template<>
bool Myless<char *>(const CHARPtr a, const CHARPtr b)
{
return strcmp(a, b) < 0;
}
template<typename T,typename PRE>
void sort(T str[],int len,PRE pre)
{
for (int i = 0; i < len; i++)
{
for (int j = i+1; j < len; j++)
{
if (pre(str[i],str[j]))
{
T tmp = str[i];
str[i] = str[j];
str[j] = tmp;
}
}
}
for (int i = 0; i < len; i++)
{
cout << str[i] << " ";
}
cout << endl;
}
int main()
{
int str[10] = { 50, 10, 25, 16, 58, 2, 0, 15, 25, 12 };
sort(str, 10, Mygre<int>);
sort(str, 10, Myless<int>);
char *arr[] = {"abc","bca","cba"};
sort(arr, 3, Mygre<char*>);
sort(arr, 3, Myless<char*>);
return 0;
}
二、类模版
是对一批仅仅成员数据类型不同的类的抽象,程序员只要为这一批类所组成的整个类家族创建一个类模板,给出一套程序代码,就可以用来生成多种具体的类,(这类可以看作是类模板的实例),从而大大提高编程的效率。
模板的类型参数由关键字class 或关键字typename 及其后的标识符构成。在模板参数表中关键字class 和typename 的意义相同。
1、格式:
template <类型名 参数名1,类型名 参数名2,…>
class 类名
{
类声明体
};
2、类模板的实例化
1)隐式实例化
template<typename T>
class Person
{
public:
A(T name)
{
_name = name;
}
void show()
{
cout<<"_name:"<< _name <<endl;
}
private:
T _name;
};
int main()
{
//显示模板实参的隐式实例化
Person<char> a('a');
a.show();
}
2)显示实例化
template<typename T>
class Person
{
public:
A(T name)
{
_name = name;
}
void show()
{
cout<<"_name:"<< _name <<endl;
}
private:
T _name;
};
template class Person<int>;
3、类模板中成员方法的模板和类模板中成员方法的模板的特例化
template<typename T>
class Carry
{
public:
Carry(int resize = 2)
{
cout << "Carry(int resize = 0)" << endl;
_arr = new T[resize];
_len = resize;
_sizeVal = 0;
}
~Carry()
{
cout << "~Carry()" << endl;
delete[]_arr;
}
//类模版中成员方法的模板
template<typename U>
int find(U val);
{
cout << "template<typename U> int find(U val)" << endl;
for (int i = 0; i < _sizeVal; i++)
{
if (_arr[i] == val)
{
return i;
}
}
return -1;
}
//类模版中成员方法的模板的特例化
template<>
int find<char*>(char * val);
{
cout << "template<> int find<char*>(char * val)" << endl;
for (int i = 0; i < _sizeVal; i++)
{
if (strcmp(_arr[i],val) == 0)
{
return i;
}
}
return -1;
}
private:
T *_arr;
int _len;
int _sizeVal;
};