**
前言
为了解决代码复用和数据类型给程序设计带来的困扰引入了模板。
模板
1. 分类
模板分成函数模板和类模板两大类。
2. 函数模板
1.声明
template<typename 占位符1,typename 占位符2,...,typename 占位符n>
template为模板声明关键字;尖括号<>内为模板参数列表
占位符1,占位符2,…,占位符n为数据类型
举例如下:
template<typename T,typename R,typename S>
T maxt(R x, S y){
return (x>y)?x:y;
}
不难看出,T,R,S为类型占位符,这种模板的目标实体与模板同名的函数称为函数模板。
2.函数模板调用
模板名<实际类型1,实际类型2,...,实际类型n>(函数实参);
当函数的两个参数为同一数据类型时,函数模板中只声明一个类型占位符就行,如代码:
maxt<int,int>(4,6);
//可简写为:
maxt<int>(4,6);
maxt<double,double>(4.2,7.9);
//可简写为:
maxt<double>(4.2,7.9);
3.编译器声明实体函数
需搞清函数模板与实体函数是怎么回事
函数模板:为实现某种功能的一种算法,与数据类型无关仅与逻辑相关
实体函数:包含实际数据类型的一个函数,可直接用来实现某一具体的功能。
template<typename T,typename R,typename S>
T maxt(R x, S y){
return (x>y)?x:y;
}
int main(int argc,char *argv[])
{
maxt<int,int,int>(4,2);
maxt<double,double,double>(3.4,6.7);
return();
}
该例子相当于未用模板的程序:
#include<iostream>
using namespace std;
//数据类型为int
int maxt(int x,int y)
{
return(x>y)?x:y;
}
//数据类型为double
double maxt(double x,double y)
{
return(x>y)?x:y;
}
//主函数
int main(int argc,char *argv[])
{
cout<<maxt(4,6)<<endl;
cout<<maxt(3.4,6.7)<<endl;
return 0;
}
调用函数时,通常会有参数传递,函数参数的类型往往就是模板参数将来的数据类型。因此,在编译器可自动推测出模板参数的实际类型时,模板调用语句中尖括号可省略。
3. 类模板
类模板的声明与函数模板一样。例如代码:
template<typename T>
class Circle
{
private:
T Radius;
public:
Circle(T r){Radius=r;};
T Area(){
return PI*Radius*Radius;
};
};
上述声明了一个圆模板。
类模板调用
类名<模板实参>对象名;
如:Cirlce<int>(100);
与实体类相同,类模板也可将其成员函数实现在类模板之外,但必须将它们声明为函数模板。
#include<iostream>
using namespace std;
//Circle类模板
template<typename T>
class Circle
{
private:
T Radius;
public:
Circle(T r);
T Area();
};
//主函数-------------------------
int main(){
//定义一个int型对象
Circle<int>circle_1(10);
cout<<circle_1.Area()<<endl;
//定义一个double型对象
Circle<double>circle_2(12.456);
cout<<circle_2.Area()<<endl;
}
//类模板外实现的类成员函数-------------
template<typename T>
Circle<T>::Circle(T r)
{
Radius=r;
}
template<typename T>
Circle<T>::Area()
{
return PI*Radius*Radius;
}
4. 注意小结
模板参数列表中定义的类型占位符的作用域仅限于本模板