感谢ljj
1 模板的概念
模板:类型参数化后的样板,模板分为函数模板和类模板
函数模板:同一个函数操作不同类型的对象
类模板:表示一组类
模板函数:函数模板实例化以后叫做模板函数
模板类:类模板实例化以后叫做模板类
2 函数模板与模板函数
函数模板定义
声明:
template <class Type…>
返回类型 函数名(参数表)
{
使用Type的函数体
}
template<typename 类型参数>
返回类型 函数名(模板型参表)
{
函数体
}
就是在定义函数前在方括号内对类型进行命名,然后在后面的函数中使用这个类型。
由函数模板生成模板函数
函数模板不是函数,不对应可执行代码。其定义是对一类函数的描述,只有实例化为模板函数后才能被执行。
带有template的内容是函数模板,编译器生成的是模板函数
重载一般是参数类型不同时操作有一定不同的函数。
模板是参数类型不同,但是逻辑操作完全相同。
函数模板是模板的定义,定义中用到的是通用的参数类型,它可以是任意类型T为参数和返回值。
模板函数是实实在在的函数定义,它是由编译系统碰见具体函数调用时生成的,具有函数代码。
函数模板的使用
1.多个类型必须都用class修饰
#include <iostream.h> //C++IO流头文件
//定义两个参数的函数模板
template<class type1, class type2>
void myfunc(type1 x, type2 y)
{
cout<<x<< “ “ << y<<endl;
}
2.在template语句与函数模板定义语句之间不允许有别的语句
template<class T>
int i; //编译错误,不允许有别的语句
T max(T x, T y)
{
return (x>y)?x:y;
}
3.函数可以带有模板参数表中未给出的、已存在的数据类型的参数。比如int
4.函数模板中没有隐式的类型转换
template<class T>
T max(T x, T y)
{ return (x>y)?x:y; }
void func(int i,char c)
{
max(i, i); //正确 ,调用max(int,int)
max(c, c); //正确 ,调用max(char,char)
max(i, c); //错误 ,类型不匹配
max(c, i); //错误 ,类型不匹配
}
这种情况下使用非模板函数重载函数模板。
template<class T>
T max(T x, T y)
{
return (x>y)?x:y;
}
int max(int, int);//只声明一个非模板函数的原型
void func(int i,char c)
{
max(i, i); //正确 ,调用max(int,int)
max(c, c); //正确 ,调用max(char,char)
max(i, c); //正确 ,调用 max(int,int),使用隐式类型转换
max(c, i); //正确 ,调用max(int,int),使用隐式类型转换
}
或者定义一个完整的非模板函数重载模板函数
char *max(char *x, char *y)
{
return (strcmp(x,y)>0)?x:y;
}
模板函数重载的调用顺序
1.寻找一个参数完全匹配的函数,如果找到就调用它。
2.寻找一个函数模板,将其实例化,产生一个匹配的模板函数。若找到了,就调用它。
3,若(1)和(2)都失败,再试一试低一级的对函数的重载方法。例如通过类型转换可产生参数匹配等,若找到了,就调用它。若(1),(2),(3)均未找到匹配的函数,则是一个错误的调用。如果在第(1)步有多于一个的选择,那么这个调用是意义不明确的,是一个错误调用。
3 类模板与模板类
类模板的定义和使用
template <class Type>
class ClassName
{
类的定义体
};
或
template <typename Type>
class ClassName
{
//具体内容
};
就是在声明前加上类型的声明,然后定义一个类。
调用方法
ClassName<类型实参表> object
例子
template<class Type>
class Stack
{
Type data[100]; //注意这里的Type
int top;
public:
Stack(); //构造函数
void push(Type e); //出栈
Type pop(); //入栈
};
template<class Type>
Stack<Type>::Stack()
{ top=0; }
template<class Type>
void Stack<Type>::push(Type e)
{ data[top++]=e; }
template<class Type>
Type Stack<Type>::pop()
{ return data[--top]; }
模板函数说明
1.在每个类模板定义之前,都需要在前面加上模板声明,如:
template
类模板在使用的时候,必须在名字后面缀上模板参数 ,例如stack。
(2)模板类可以有多个模板参数