来自:http://blog.csdn.net/badboyfind/archive/2007/10/18/1830330.aspx
1.函数模板
函数模板定义的一般格式为:
template < class 类型形参名1,... ,class 类型形参名n >
返回类型 函数模板名 ( 形参表 ) { 函数体 }
注意:
1) 应在“返回类型”或“形参表”或“函数体”中使用上述的“类型形参名” 。
2) 调用处则类似于一般函数,用户只需给出具体的实参。
3) 模板函数调用时,不进行实参到形参类型的自动转换。
1.1 函数模板例1:
定义一个函数模板max,而后对它进行不同的调用:
#include <iostream.h>
template <class T>
T max (T a, T b)
{
if(a>b)
return a;
else
return b;
}
void main()
{
int i1 = -11, i2 = 0 ;
double d1, d2;
cout<<max(i1,i2)<<endl;
//由实参i1,i2,系统可确定“类型形参T”对应于int
cout<<max(23,-56)<<endl;
cout<<max('f', 'k')<<endl;
cin>>d1>>d2;
cout<<max(d1,d2)<<endl;
//cout<<"max(23,-5.6) = "<<max(23,-5.6)<<endl;
//出错! 不进行实参到形参类型的自动转换,因为23和-5.6的类型不一致
}
程序执行后的显示结果如下:
int i1=-11, i2=0; => max(i1,i2) = 0
max(23,-56) = 23
char c1='T', c2='F'; => max(c1,c2) = T
max('f', 'k') = k
input double d1, d2 : 123.45 99.67
d1=123.45, d2=99.67 => max(d1,d2) = 123.45
1.2函数模板例2 -- 函数模板与函数重载
定义一个函数模板与一个函数,它们都叫做min,C++允许这种函数模板与函数同名的所谓重载使用方法。但注意,在这种情况下,每当遇见函数调用时,C++编译器都将首先检查是否存在重载函数,若匹配成功则调用该函数,否则再去匹配函数模板。
#include <iostream.h>
#include <string.h>
template <class type>
type min (type a, type b)
{
//type型的a与b要能够进行“<”比较运算!
return (a<b?a:b);
}
char* min (char* a, char* b)
{
//函数min,字符串型参数,不能直接使用“<”来进行比较
return (strcmp(a,b)<0?a:b);
}
void main()
{
cout<<min(3,-10)<<endl; //使用函数模板
cout<<min(2.5,99.5)<<endl;
cout<<min('m','c')<<endl;
char* str1="The C program", * str2="The C++ program";
cout<<min(str1, str2)<<endl; //使用重载函数!
}
1.3 函数模板例3 -- 二函数模板重载
定义两个函数模板,它们都叫做sum,都使用了一个类型参数Type,但两者的形参个数不同,C++允许使用这种函数模板重载的方法。
注意,参数表中允许出现与类型形参Type无关的其它类型的参数,如“int size”。
#include <iostream.h>
template <class Type>
Type sum (Type * array, int size )
{
//求array数组前size个元素之和
Type total=0;
for (int i=0;i<size;i++)
total+=*(array+i);
return total;
}
template <class Type>
Type sum (Type * a1, Type * a2, int size )
{
//求a1数组与a2数组前size个元素之和
Type total=0;
for (int i=0;i<size;i++)
total+=a1[i]+a2[i];
return total;
}
void main() {
int a1[10],a2[8];
float af[10];
... //为数组分量定值
cout<<sum(a1,10)<<endl; //求出a1数组前10个元素之和并输出
cout<<sum(af,10)<<endl;
cout<<sum(a1,a2,8)<<endl; //求a1与a2数组前8个元素之和并输出
}
2.类模板
2.1类模板的概念及其定义格式
利用类模板(带类型参数或普通参数的类),一次就可定义出具有共性的一组类。 即,可使得所定义类中的某些数据成员、某些成员函数的参数、某些成员函数的返回值都可以是任意类型的。
类模板定义格式如下:
template < 类型形参或普通形参1的说明,... ,类型形参或普通形参n的说明 >
class 类模板名
{
带上述类型形参或普通形参名的类定义体;
}
说明类型形参时,使用“class 类型形参名”的方式,说明普通形参时,使用“<类型> 普通形参名”的方式。
注意:
1) 类定义体中应使用上述的“类型形参名”及“普通形参名”。
2) 利用类模板说明类对象时,要随类模板名同时给出对应于类型形参或普通形参的具体实参(从而实例化为一个具体的类)。
说明格式为:
类模板名 < 形参1的相应实参,... ,形参n的相应实参 >
注意:类型形参的相应实参为类型名,而普通形参的相应实参必须为一个常量。
3) 类模板的成员函数既可以在类体内进行说明(自动按内联函数处理),也可以在类体外进行说明。
在类体外说明(定义)时使用如下格式:
template < 形参1的说明,... ,形参n的说明 >
返回类型 类模板名 < 形参1的名字,... ,形参n的名字 >::函数名( 形参表 )
{
... //函数体
};
上述的“形参1的名字”来自于“形参1的说明”,由“甩掉”说明部分的“类型”而得,是对类型形参或普通形参的使用。而
“类模板名 < 形参1的名字,... ,形参n的名字 >::”所起的作用正是在类体外定义成员函数时在函数名前所加的类限定符!
例如,对具有一个类型参数T的类模板TestClass,在类体外定义其成员函数getData时的大致样式如下:
template <class T>
T TestClass<T>::getData( 形参表 )
{
... //函数体
};
其中的“TestClass<T>::”所起的作用正是在类体外定义成员函数时在函数名前所加的类限定符!
2.2仅使用类型参数的类模板示例
#include <iostream.h>
template <class T>
class TestClass
{
public:
T buffer[10]; //T类型的数据成员buffer数组大小固定为10 (灵活性差!)
T getData(int j); //获取T类型buffer(数组)的第j个分量
};
template <class T>
T TestClass<T>::getData(int j)
{
return *(buffer+j);
};
void main()
{
TestClass<char> ClassInstA; //char取代T,从而实例化为一个具体的类
char cArr[6]="abcde";
for(int i=0; i<5; i++)
ClassInstA.buffer[i]=cArr[i];
for(i=0; i<5; i++)
{
char res=ClassInstA.getData(i);
cout<<res<<" ";
}
cout<<endl;
TestClass<double> ClassInstF; //实例化为另外一个具体的类
double fArr[6]={12.1, 23.2, 34.3, 45.4, 56.5, 67.6};
for(i=0; i<6; i++)
ClassInstF.buffer[i]=fArr[i]-10;
for(i=0; i<6; i++)
{
double res=ClassInstF.getData(i);
cout<<res<<" ";
}
cout<<endl;
}
程序执行后的显示结果如下:
a b c d e
2.1 13.2 24.3 35.4 46.5 57.6
2.3仅使用普通参数(非类型参数)的类模板示例
#include <iostream.h>
template <int i>
class TestClass
{
public:
int buffer[i];
//使buffer的大小可变化,但其类型则固定为int(灵活性差!)
int getData(int j);
};
template <int i>
int TestClass<i>::getData(int j)
{
return *(buffer+j);
};
void main()
{
TestClass<6> ClassInstF;
double fArr[6]={12.1, 23.2, 34.3, 45.4, 56.5, 67.6};
for(i=0; i<6; i++)
ClassInstF.buffer[i]=fArr[i]-10;
for(i=0; i<6; i++)
{
double res=ClassInstF.getData(i);
cout<<res<<" ";
}
cout<<endl;
}
程序执行后的显示结果如下:
2 13 24 35 46 57
2.4既使用类型参数又使用普通参数的类模板示例
#include <iostream.h>
#include "string.h"
template <class T, int i>
class TestClass
{
public:
T buffer[i]; //T类型的buffer,其大小随普通形参i的值变化(灵活性大!)
T getData(int j);
};
template <class T, int i>
T TestClass<T,i>::getData(int j)
{
return *(buffer+j);
};
void main()
{
TestClass<char, 5> ClassInstA;
char cArr[6]="abcde";
strcpy(ClassInstA.buffer, cArr);
for(int i=0; i<5; i++)
{
char res=ClassInstA.getData(i);
cout<<res<<" ";
}
cout<<endl;
TestClass<double, 6> ClassInstF;
double fArr[6]={12.1, 23.2, 34.3, 45.4, 56.5, 67.6};
for(i=0; i<6; i++)
ClassInstF.buffer[i]=fArr[i]-10;
for(i=0; i<6; i++)
{
double res=ClassInstF.getData(i);
cout<<res<<" ";
}
cout<<endl;
}
程序执行后的显示结果如下:
a b c d e
2.1 13.2 24.3 35.4 46.5 57.6
补充例子如下:
#include <iostream>
using namespace std;
template<class T>
void Swap(T &a,T &b);
struct people
{
char name[10];
int age;
};
void Swap(people&a,people&b);
template<>void Swap<people>(people&p1,people&p2);
void show(people&p);
int main()
{
int i=10,j=20;
cout<<"初始值i="<<i<<",j="<<j<<"./n";
Swap(i,j);
cout<<"现在,i="<<i<<",j="<<j<<"./n";
people Jack={"Jack",44};
people Mick={"Mick",24};
cout<<"交换之前:/n";
show(Jack);
show(Mick);
Swap(Jack,Mick);
cout<<"交换后:/n";
show(Jack);
show(Mick);
return 0;
}
template<class T>
void Swap(T &a,T &b)
{
cout<<"执行Swap函数模板进行交换..../n";
T temp;
temp=a;
a=b;
b=temp;
}
void Swap(people&a,people&b)
{
cout<<"执行非模板函数/n";
int Age;
Age=a.age;
a.age=b.age;
b.age=Age;
}
template<>void Swap<people>(people &a,people &b)
{
cout<<"执行具体化模板函数/n";
int Age;
Age=a.age;
a.age=b.age;
b.age=Age;
}
void show(people&p)
{
cout<<p.name<<"的年龄:"<<p.age<<endl;
}
执行结果:
初始值i=10,j=20.
执行Swap函数模板进行交换....
现在,i=20,j=10.
交换之前:
Jack的年龄:44
Mick的年龄:24
执行非模板函数
交换后:
Jack的年龄:24
Mick的年龄:44
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/badboyfind/archive/2007/10/18/1830330.aspx