模板把函数或类要处理的数据类型参数化,即表现为参数的多态性。
模板的概念
强类型的严格性与灵活性
介绍一个概念
强类型语言:一旦某个变量被定义类型,若不经过强制转换,则永远是该数据类型。(在编译时即可)
弱类型语言:可根据环境变化自动转换。
强类型的程序设计迫使程序员为逻辑结构相同而具体数据类型不同的对象编写模式一致的代码,但因为无法抽取其中的共性,所以不利于程序的扩充和维护。
解决冲突的途径
- 利用宏函数(不展开讲了,C++不是太提倡这个,因为它老会引入一些意想不到的问题)
- 为各种类型都重载这一函数(还是比较麻烦)
- 放松类型检查,在编译期间忽略这些类型匹配问题,而在运行期间进行类型匹配检查(但是在程序运行时可能出现类型不兼容的错误。)
- 类属(最理想的方法,直接将数据类型作为类的参数,就像函数可以将数据作为参数一样)【在C++中,可以采用模板机制实现类属】
模板的概念
模板:一种参数化多态性(一对多)的工具,可以为逻辑功能相同而类型不同的程序提供代码共享的机制。
分类:
- 函数模板(带类属参数的函数)
- 类模板(带类属参数的类)
注意,模板不是一个实实在在的函数或类,仅仅是函数或类的描述。而且模板运算对象的类型不是实际的数据类型,而是一种参数化的类型。
模板的类属参数由调用实际参数的具体数据类型替换,并由编译器生成一段真正可以运行的代码。(这个过程被称作实例化)
初步了解概念之后,就可以进行代码实现了。
函数模板
定义格式
template<模板参数表>
<返回值类型><函数名>(<参数表>)
{
<函数体>
}
- template是定义模板的关键字
- <模板参数表>包含一个或多个用逗号分开的模板参数项,每一项由class或typename开始,后跟用户命名的标识符,此标识符为模板参数,表示数据类型。
举个例子
//定义函数模板求两个数中的较大值
template<typename T>//编译程序会根据函数调用时的实际数据类型产生相应的函数
T max(T a,T b)
{return a>b?a:b;}
- <参数表>中可以使用模板函数或一般函数,但其中至少有一个形参类型是<模板参数表>中的形参定义的,并且在<模板参数表>中的每个模板参数都必须在<参数表>中得到使用
函数模板的实例化
//利用函数模板求两个数中的较大值
#include<iostream>
#include<string>
using namespace std;
template<typename T>
T max(T& a,T& b)
{return a>b?a:b;}
int main()
{
int a,b;
cout<<"Input two integers to a&b:"<<endl;
cin>>a>>b;
cout<<"max("<<a<<","<<b<<")="<<max(a,b)<<endl;
char c,d;
cout<<"Input two chars to c&d:"<<endl;
cin>>c>>d;
cout<<"max("<<"\'"<<c<<"\'"<<","<<"\'"<<d<<"\'"<<")=";
cout<<max(c,d)<<endl;
float x,y;
cout<<"Input two floats to x&y:"<<endl;
cin>>x>>y;
cout<<"max("<<x<<","<<y<<")="<<max(x,y)<<endl;
cout<<"Input two strings to p&h:"<<endl;
string p,h;
cin>>p>>h;
cout<<"max("<<"\""<<p<<"\""<<","<<"\""<<h<<"\""<<")=";
cout<<max(p,h)<<endl;
}
输出:
Input two integers to a&b:
4 5
max(4,5)=5
Input two chars to c&d:
q w
max('q','w')=w
Input two floats to x&y:
3.4 5.6
max(3.4,5.6)=5.6
Input two strings to p&h:
qaz wsw
max("qaz","wsw")=wsw
函数模板的声明和定义必须是全局作用域,而且模板不能被声明成类的成员函数。
函数模板的重载
//示例函数模板的重载
#include<string>
using namespace std;
template<typename T>
T max(T& a,T& b)
{return a>b?a:b;}
template<typename T>
T max(T a[],int n)
{
T temp;
int i;
temp=a[0];
for(i=1;i<=n-1;i++)
if(a[i]>temp)
temp=a[i];
return temp;
}
int main()
{
int a,b;
cout<<"Input two integers to a&b:"<<endl;
cin>>a>>b;
cout<<"max("<<a<<","<<b<<")="<<max(a,b)<<endl;
int i,aa[10]={3,7,9,11,0,6,7,5,4,2};
cout<<"The original array:"<<endl;
for(i=0;i<10;i++)
cout<<aa[i]<<" ";
cout<<endl;
cout<<"max of 10 integers is"<<max(aa,10)<<endl;
return 0;
}
输出:
Input two integers to a&b:
4 5
max(4,5)=5
The original array:
3 7 9 11 0 6 7 5 4 2
max of 10 integers is11
C++编译器根据调用的参数类型和个数选择可用于实例化的函数模板
用普通函数重载函数模板
函数模板实例化时,实际参数类型将替换模板参数。虽然这种参数替换具有类型检查功能,当却没有普通传值参数的类型转化机制。由于函数模板无法预知隐式的类型转换,可以用非模板函数重载一个同名的函数模板
#include<iostream>
using namespace std;
template<typename T>
T max(T& a,T& b)
{return a>b?a:b;}
template<typename T>
int max(int a,float b)
{
return a>b?a:b;
}
int main()
{
char a='4',b='5';
int c=5;
cout<<"max("<<"\'"<<a<<"\'"<<","<<"\'"<<b<<"\'"<<")=";
cout<<max(a,b)<<endl;
cout<<"max("<<"\'"<<a<<"\'"<<","<<b<<")="<<max(a,c)<<endl;
return 0;
}
(无法运行,奇了怪了。。)
用特定函数重载函数模板
#include<iostream>
using namespace std;
template<typename T>
T max(T& a,T& b)
{return a>b?a:b;}
template<typename T>
int max(int a,float b)
{
return a>b?a:b;
}
char *max(char *a,char *b)
{
return strcmp(a,b)>0?a:b;
}
int main()
{
char a='4',b='5';
int c=5;
cout<<"max("<<"\'"<<a<<"\'"<<","<<"\'"<<b<<"\'"<<")=";
cout<<max(a,b)<<endl;
cout<<"max("<<"\'"<<a<<"\'"<<","<<b<<")="<<max(a,c)<<endl;
char *p,*h;
p="qaz";
h="wsw";
cout<<"max("<<"\""<<p<<"\""<<","<<"\""<<h<<"\""<<")=";
cout<<max(p,h)<<endl;
return 0;
}
(得了,这个也是错的,先做个记号,等问出原因再回来补充)