模板--函数模板与函数模板,类模板与模板类,重载模板函数

1.模板的作用:

能够快速建立具有类型安全类库集合函数集合。模板可以让程序对任何其他数据类型进行同样范式的处理


例如:
void swap(int& a, int& b){
     int temp=a;
     a=b;
     b=temp;
}
void swap(double& a, double& b){
    double temp=a;
    a=b;
    b=temp;
}
这两个函数目的都是对a,b进行交换,但是由于它们的类型不同,而写了两个几乎一样的程序,这是一种冗余,可以用模板来简化

函数模板:
template<class T>void swap(T& a, T& b){       
   T temp=a;
   a=b;
   b=temp;
}

int main(){

   int a=1;
   int b=2;
   double c=1;
   double d=2;
   swap(a,b);     //  结果a=2,b=1        当编译器识别swap(a,b)的时候,它会产生一个模板函数swap(int&,int&){...};
   swap(c,d);     //  结果c=2,d=1         当编译器识别swap(c,d)的时候,它会产生一个模板函数swap(double&,double&){...};
}
注意:
函数模板和模板函数的区别:
函数模板:其实就是函数的一个定义,编译器没有实实在在为其产生任何执行代码。
模板函数:其实是函数模板的一个实例,编译器为参数为不同数据类型的函数调用创建不同的模板函数

两者的关系其实类与对象的关系相似


再例如:
class Cat{
}
class Dog{
}
class CatList{
   public:
     List();
     void add(Cat&);
     void remove(Cat&);
     Cat* Find(Cat&);
     ~List();

   private:
   ....
}
class DogList{
   public:
     List();
     void add(Dog&);
     void remove(Dog&);
     Cat* Find(Dog&);
     ~List();

   private:
     ....
}
这两个类其实目的是要建立一条链表,链表操作一样,但是由于结点类型的不同,写了两个几乎一样的程序,这是一种冗余,可以用模板简化。

类模板:
template <class T> class List{
  public:
     List();
     void add(T&);
     void remove(T&);
     Cat* Find(T&);
     ~List();

   private:
     ....

}
int main(){
   Cat cat;
   List<T> catList;    //  当编译器识别List<T> catList的时候,它会产生一个模板类,class CatList{...},如上面的CatList定义所示;
   catList.add(cat);    //  当编译器识别List<T> dogList的时候,它会产生一个模板类,class DogList{...},如上面的DogList定义所示;

   Dog dog;
   List<T> dogList;
   dogList.find(dog);
}
注意:
类模板和模板类的区别与函数模板和模板函数的区别相同。


2.函数模板比宏定义多一个类型检查:

#define max(a,b) ((a)>(b))?(a):(b)     // 宏定义的a,b 没有类型检查机制,那么int a,char b也拿来比较,这会出错。 

template <class T> T max(T& a, T&b){
  return  ((a)>(b))?a:b;      //使用函数模板可 对不同的数据类型进行相应的模板函数匹配,那么它是 有类型检查的。
}

当然T类的>需要定义,因为 不是所有的类型都可以>比较 ,例如char*类型就不能;等一下讲重载模板函数有涉及。


3.重载模板函数:

int max(int& a,int&b){
     return  ((a)>(b))?a:b; 
}

float max(float& a, float& b){
     return  ((a)>(b))?a:b; 
}

假如还没有相应的函数模板,那么如果输入的是字符呢?怎么处理呢?
如:
max('3','5');   // 结果是53(这是5的ASII码),因为没有相应的char max(char a,char b);所以会自动匹配int max(int,int),这样的话只会输出53.

假如有了下面的函数模板,那么 编译器在看到max('3','5');的时候,会 产生相应的模板函数char max(char,char);这样就可以输出所期望的较大值5.

函数模板为:
template <class T> T max(T& a, T&b){
  return  ((a)>(b))?a:b;       
}

就算有了相应的函数模板,但是如果输入的是字符串呢?字符串是不可直接>比较的,而是需要函数strcmp(),所以还是没有相应的模板函数啊?

这时候就 需要重载模板函数

char* max(char* a, char* b){
   return ( strcmp(a,b)?a:b);    
}

int main(){
   max("Hello","Lawliet");  // 当 编译器看到max("Hello","Lawliet")的时候,首先 试图匹配重载函数,找到了匹配的char* max(char*,char*)那么就 不用                     
                                           再寻找模板的匹配,那么就不会像上面的int max(int*,int*)那么会产生一段模板函数的代码。
}


4.模板(包括类的定义,以及类成员函数的声明和定义)应放在该头文件中。
原因是
1.类的定义和类成员函数的声明像普通函数一样要放在头文件中。
2.既然模板本身是一个“定义”,就是要被include的,所以它类成员函数的定义也必须明确地包含在头文件中,才能使得被include的时候可以使用。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值