1-1 为什么要一用函数模板呢。
#include <iostream>
using namespace std;
/*
void myswap(int &a, int &b)
{
int t = a;
a = b;
b = t;
}
void myswap(char &a, char &b)
{
char t = a;
a = b;
b = t;
}
*/
//template 关键字告诉C++编译器 我要开始泛型了.你不要随便报错
//数据类型T 参数化数据类型
template <typename T>
void myswap(T &a, T &b)
{
T t;
t = a;
a = b;
b = t;
}
void main()
{
//char a = 'c';
int x = 1;
int y = 2;
myswap(x, y); //自动数据类型 推导的方式
float a = 2.0;
float b = 3.0;
myswap(a, b); //自动数据类型 推导的方式
myswap<float>(a, b); //显示类型调用
cout<<"hello..."<<endl;
system("pause");
return ;
}
1-2 函数模板可以做函数的参数
#include <iostream>
using namespace std;
template<typename T, typename T2>
void sortArray(T *a, T2 num)
{
T tmp ;
int i, j ;
for (i=0; i<num; i++)
{
for (j=i+1; j<num; j++)
{
if (a[i] < a[j])
{
tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
}
}
}
template<class T>
void pirntArray(T *a, int num)
{
int i = 0;
for (i=0; i<num; i++)
{
cout<<a[i]<<" ";
}
}
void main()
{
int num = 0;
char a[] = "ddadeeettttt";
num = strlen(a);
printf("排序之前\n");
pirntArray<char>(a, num);
sortArray<char, int>(a, num); //显示类型调用 模板函数 <>
printf("排序之后\n");
pirntArray<char>(a, num);
cout<<"hello..."<<endl;
system("pause");
return ;
}
1-3 函数模板遇上函数重载
函数模板和普通函数区别结论:
函数模板不允许自动类型转化
普通函数能够进行自动类型转换函数模板和普通函数在一起,调用规则:
1 函数模板可以像普通函数一样被重载
2 C++编译器优先考虑普通函数
3 如果函数模板可以产生一个更好的匹配,那么选择模板
不妨看下面的案例分析一波:
#include <iostream>
using namespace std;
template <typename T>
void myswap(T &a, T &b)
{
T t;
t = a;
a = b;
b = t;
cout<<"myswap 模板函数do"<<endl;
}
void myswap(char &a, int &b)
{
int t;
t = a;
a = b;
b = t;
cout<<"myswap 普通函数do"<<endl;
}
void main()
{
char cData = 'a';
int iData = 2;
//myswap<int>(cData, iData); //结论 函数模板不提供隐式的数据类型转换 必须是严格的匹配
myswap(cData, iData);
//myswap(iData, cData);
cout<<"hello..."<<endl;
system("pause");
return ;
}
1-4 函数模板机制结论:
编译器并不是把函数模板处理成能够处理任意类的函数
编译器从函数模板通过具体类型产生不同的函数
编译器会对函数模板进行两次编译
在声明的地方对模板代码本身进行编译;在调用的地方对参数替换后的代码进行编译。
2.1 可以这样声明和使用类模板:
1) 先写出一个实际的类。由于其语义明确,含义清楚,一般不会出错。
2) 将此类中准备改变的类型名(如int要改变为float或char)改用一个自己指定的虚拟类型名.
3) 在类声明前面加入一行,格式为:
template <class 虚拟类型参数>
如:
template <class numtype> //注意本行末尾无分号
class Compare
{…}; //类体
4) 用类模板定义对象时用以下形式:
类模板名<实际类型名> 对象名;
类模板名<实际类型名> 对象名(实参表列);
如:
Compare<int> cmp;
Compare<int> cmp(3,7);
5)如果在类模板外定义成员函数,应写成类模板形式:
template <class 虚拟类型参数>
函数类型 类模板名<虚拟类型参数>::成员函数名(函数形参表列) {…}
2.2 关于类模板的几点说明:
1) 类模板的类型参数可以有一个或多个,每个类型前面都必须加class,如:
template <class T1,class T2>
class someclass
{…};
在定义对象时分别代入实际的类型名,如:
someclass<int,double> obj;
2) 和使用类一样,使用类模板时要注意其作用域,只能在其有效作用域内用它定义对象。
3) 模板可以有层次,一个类模板可以作为基类,派生出派生模板类。
2.3 类模板在项目开发中的应用
小结
模板是C++类型参数化的多态工具。C++提供函数模板和类模板。
模板定义以模板说明开始。类属参数必须在模板定义中至少出现一次。
同一个类属参数可以用于多个模板。
类属参数可用于函数的参数类型、返回类型和声明函数中的变量。
模板由编译器根据实际数据类型实例化,生成可执行代码。实例化的函数。
模板称为模板函数;实例化的类模板称为模板类。
函数模板可以用多种方式重载。
类模板可以在类层次中使用 。