一,模板的概念。
引入模板的原因:
我们已经学过重载,对重载函数而言,C++的检查机制能通过函数参数的不同及所属类的不同。正确的调用重载函数。例如,为求两个数的最大值,我们定义MAX()函数需要对不同的数据类型分别定义不同重载版本。
Int max(int x,int y);
{return(x>y)?x:y ;
}
float max( float x,float y){
return (x>y)? x:y ;}
double max(double x,double y)
{return (c>y)? x:y ;}
但如果在主函数中,我们分别定义了 char a,b;
在执行max(a,b);时 程序就会出错,因为我们没有定义char类型的重载版本。
现在,我们再重新审视上述的max()函数,它们都具有同样的功能,即求两个数的最大值,能否只写一套代码解决这个问题呢?这样就会避免因重载函数定义不全面而带来的调用错误。为解决上述问题C++引入模板机制,模板定义:模板就是实现代码重用机制的一种工具,它可以实现类型参数化,即把类型定义为参数,从而实现了真正的代码可重用性。模板分类:磨板分为函数模板后,当编译系统发现了一个对应的函数调用事,将根据实参的类型来确认是否匹配函数模板中对应的形参然后生成一个重载函数,称该重载函数为模板函数。函数模板与模板函数的区别: 二者区别可以类比 类与对象的区别。函数 模板与类相似是模板的定义,而模板函数与对象相似。是函数模板的实例,具有程序代码。占用内存空间。同样,在说明了一个类模板后,也可以创建类模板的实例即生成模板类。类模板与模板类的区别是:类模板是模板的定义,不是一个实在的类,模板类才是实实在在的类。
二、函数模板与模板憾事
函数模板的一般生命形式如下:
template<class类型形参表>
返回类型 函数名(形参表)
{//函数定义体 }
说明: templarte是一个声明模板的关键字,表示声明一个模板关键字class不能省略,如果类型形参多余一个 ,每个形参前都要加class <类型 形参表>可以包含基本数据类型可以包含类类型.
请看以下程序:
#include<iostream.h>
template<class T> /*函数模板声明*/
T min(T x , T y)
{if(x<y ) return x;
else return y;}
void main( )
{ int n1=2,n2=10;
double d1=1.5,d2=5.6;
cout<<”较小整数:”<<min(n1,n2)<<endl;//实例化 min模板函数比较两整数
cout<<”较小实数:”<<min(d1,d2)<<endl;// 实例化min模板函数比较两双精度数
}
程序运行结果: 较小整数:2
较小实数:1.2
程序分析:main()函数中定义了两个整型变量n1 , n2 两个双精度类型变量d1 , d2然后调用min( n1, n2); 即实例化函数模板T min(T x, T y)其中T为int型,求出n1,n2中的最小值.同理调用min(d1,d2)时,求出d1,d2中的最小值.
可用下图表示函数模板实例化过程
函数模板min(x,y)
模板函数min(n1,n2)int型
模板函数min(d1,d2) double型
若main()函数中加一条cout<<min(n1,d1)<<endl;
程序将会出错,原因是模板函数T的各参数之间必须保持完全一致的类型,并不具有隐式类型转换功能.
三,类模板与模板类
1.定义一个类模板:
template<class类型形参表>
class类名{
//类定义......
};
 其中,template是声明各模板的关键字,表示声明一个模板,模板参数可以是一个,也可以是多个,但应是抽象化的结果,不应是具体的(例int,float等)类型,成员函数的参数或返回类型,前面要加上形参类型.
例如:定义一个类模板:
template<classT1,classT2>
class myclass{T1 I;//
T2 j;//
Public:
Myclass(T1 a,T2 b)//
{I=a; j=b;}
void show( )
{cout<<”I=”<<”j=”<<j<<endl;}};
在主函数中若定义了一模板类 myclass<int,double>并且声明一个类对象ob1(1  引用语句:myclass<int,double >ob(2,0.1);注意:myclass<int,double>实例化了类模板,即将T1实例为int 类型,T2为double 类型,这样我们就得到了一个模板类.然后就可以定义类对象ob1并初始化.
还可以定义另一个模板类如: myclass<double ,char>
可通过下图表示类模板与模板类的关系
类模板myclass<T!,T2>
模板类myclass(int,double)
模板类nyclass<double,char>
总结:函数模板是一类函数的抽象,代表了一类函数,这一类函数具有相同的功能,代表一 具体的函数,能被类对象调用,而函数模板绝不能被类对象调用.
类模板是对类的抽象,代表一类类,这些类具有相同的功能,但数据成员类型及成员函数返回类型和形参类型不同.模板类是类模板类的实例.代表一具体的类,可以定义类对象 ,而不能给类模板定义对象.

-------------------------------

名正言顺  
  中国有句古话:名不正则言不顺。一样东西,名字如果用的不好,不但听起来不舒服,而且真实的本质也容易被掩盖。如果一样东西有一个好名字,我们就能更容易的记住它和理解它。  
   
  在现代汉语中,许多词的重点都在后面,比如下面我们经常看到的两个词语。  
   
  冰雪聪明。  
   
  聪明冰雪。  
   
  冰雪聪明强调的是聪明,她像冰雪一样的聪明。  
   
  聪明冰雪强调的是冰雪,她很聪明,看上去更是冰雪般的玲珑剔透纯洁。  
   
  在C++中有好几个这样的术语,但是我们很多时候用的并不正确,几乎是互相替换混淆使用。下面我想彻底辨清几个术语,这样就可以避免很多概念上的混淆和使用上的错误。  
   
  这几个词是:  
   
  函数指针——指针函数  
   
  数组指针——指针数组  
   
  类模板——模板类  
   
  函数模板——模板函数  
   
  最终在使用中,我们就可以让它们实至名归,名正言顺。  
   
     
   
  1.函数指针——指针函数  
   
  函数指针的重点是指针。表示的是一个指针,它指向的是一个函数,例子:  
   
  int   (*pf)();  
   
  指针函数的重点是函数。表示的是一个函数,它的返回值是指针。例子:  
   
  int*   fun();  
   
     
   
  2.数组指针——指针数组  
   
  数组指针的重点是指针。表示的是一个指针,它指向的是一个数组,例子:  
   
  int   (*pa)[8];  
   
  指针数组的重点是数组。表示的是一个数组,它包含的元素是指针。例子;  
   
  int*   ap[8];  
   
     
   
  3.类模板——模板类(class   template——template   class)  
   
  类模板的重点是模板。表示的是一个模板,专门用于产生类的模子。例子:  
   
  template   <typename   T>  
   
  class   Vector  
   
  {  
   
              …  
   
  };  
   
  使用这个Vector模板就可以产生很多的class(类),Vector<int>、Vector<char>、Vector<   Vector<int>   >、Vector<Shape*>……。  
   
  模板类的重点是类。表示的是由一个模板生成而来的类。例子:  
   
  上面的Vector<int>、Vector<char>、……全是模板类。  
   
  这两个词很容易混淆,我看到很多文章都将其用错,甚至一些 英文 文章也是这样。将他们区分开是很重要的,你也就可以理解为什么在定义模板的头文件.h时,模板的成员函数实现也必须写在头文件.h中,而不能像普通的类(class)那样,class的声明(declaration)写在.h文件中,class的定义(definition)写在.cpp文件中。请参照Marshall   Cline的《C++   FAQ   Lite》中的[34]   Container   classes   and   templates中的[34.12]   Why   can't   I   separate   the   definition   of   my   templates   class   from   it 's   declaration   and   put   it   inside   a   .cpp   file?   URL地址是http://www.parashift.com/c++-faq-lite/containers-and-templates.html#faq-34.12  
   
  我将几句关键的段落摘录如下,英文很好理解:  
   
  In   order   for   the   compiler   to   generate   the   code,   it   must   see   both   the   template   definition   (not   just   declaration)   and   the   specific   types/whatever   used   to   "fill   in"   the   template.   For   example,   if   you're   trying   to   use   a   Foo<int>,   the   compiler   must   see   both   the   Foo   template   and   the   fact   that   you're   trying   to   make   a   specific   Foo<int>.    
   
  Suppose   you   have   a   template   Foo   defined   like   this:    
   
    template<class   T>  
    class   Foo   {  
    public:  
        Foo();  
        void   someMethod(T   x);  
    private:  
        T   x;  
    };    
   
  Along   with   similar   definitions   for   the   member   functions:    
   
    template<class   T>  
    Foo<T>::Foo()  
    {  
        ...  
    }  
     
    template<class   T>  
    void   Foo<T>::someMethod(T   x)  
    {  
        ...  
    }    
   
  Now   suppose   you   have   some   code   in   file   Bar.cpp   that   uses   Foo<int>:    
   
    //   Bar.cpp  
     
    void   blah_blah_blah()  
    {  
        ...  
        Foo<int>   f;  
        f.someMethod(5);  
        ...  
    }    
   
  Clearly   somebody   somewhere   is   going   to   have   to   use   the   "pattern"   for   the   constructor   definition   and   for   the   someMethod()   definition   and   instantiate   those   when   T   is   actually   int.   But   if   you   had   put   the   definition   of   the   constructor   and   someMethod()   into   file   Foo.cpp,   the   compiler   would   see   the   template   code   when   it   compiled   Foo.cpp   and   it   would   see   Foo<int>   when   it   compiled   Bar.cpp,   but   there   would   never   be   a   time   when   it   saw   both   the   template   code   and   Foo<int>.   So   by   rule   above,   it   could   never   generate   the   code   for   Foo<int>::someMethod().    
   
  关于一个缺省模板参数的例子:  
   
  template   <typename   T   =   int>  
   
  class   Array  
   
  {  
   
              …  
   
  };  
   
  第一次我定义这个模板并使用它的时候,是这样用的:  
   
  Array   books;//我认为有缺省模板参数,这就相当于Array<int>   books  
   
  上面的用法是错误的,编译不会通过,原因是Array不是一个类。正确的用法是Array<>   books;  
   
  这里Array<>就是一个用于缺省模板参数的类模板所生成的一个具体类。  
   
     
   
  4.函数模板——模板函数(function   template——template   function)  
   
  函数模板的重点是模板。表示的是一个模板,专门用来生产函数。例子:  
   
  template   <typename   T>  
   
  void   fun(T   a)  
   
  {  
   
              …  
   
  }  
   
  在运用的时候,可以显式(explicitly)生产模板函数,fun<int>、fun<double>、fun<Shape*>……。  
   
  也可以在使用的过程中由编译器进行模板参数推导,帮你隐式(implicitly)生成。  
   
  fun(6);//隐式生成fun<int>  
   
  fun(8.9);//隐式生成fun<double>  
   
  fun(‘a’);//   隐式生成fun<char>  
   
  Shape*   ps   =   new   Cirlcle;  
   
  fun(ps);//隐式生成fun<Shape*>  
   
     
   
  模板函数的重点是函数。表示的是由一个模板生成而来的函数。例子:  
   
  上面显式(explicitly)或者隐式(implicitly)生成的fun<int>、fun<Shape*>……都是模板函数。  
   
  关于模板本身,是一个非常庞大的主题,要把它讲清楚,需要的不是一篇文章,而是一本书,幸运的是,这本书已经有了:David   Vandevoorde,   Nicolai   M.   Josuttis写的《C++   Templates:   The   Complete   Guide》。可惜在大陆买不到纸版,不过有一个 电子 版在网上流传。  
   
     
   
  模板本身的使用是很受限制的,一般来说,它们就只是一个产生类和函数的模子。除此之外,运用的领域非常少了,所以不可能有什么模板指针存在的,即指向模板的指针,这是因为在C++中,模板就是一个代码的代码生产工具,在最终的代码中,根本就没有模板本身存在,只有模板具现出来的具体类和具体函数的代码存在。  
   
  但是类模板(class   template)还可以作为模板的模板参数(template   template   parameter)使用,在Andrei   Alexandrescu的《Modern   C++   Design》中的基于策略的设计(Policy   based   Design)中大量的用到。  
   
  template<   typename   T,   template<typename   U>   class   Y>  
   
  class   Foo  
   
  {  
   
              …  
   
  };  
   
     
   
  从文章的讨论中,可以看到,名字是非常重要的,如果对名字的使用不恰当的话,会引起很多的麻烦和误解。我们在实际的程序中各种标识符的命名也是一门学问,为了清晰易懂,有时候还是需要付出一定的代价。  
   
  最后提醒:在本文的几个术语中, 语言 的重心在后面,前面的词是作为形容词使用的。  
   
  吴桐写于2003.6.1

模板函数与函数模板 类模板和模板的说明相关推荐

  1. EyouCMS精美简洁作文范文网站模板/易优CMS资讯类企业网站模板

    EyouCMS精美简洁作文范文网站模板,易优CMS资讯类企业网站模板,适用于博客.文章.资讯类网站使用.模板自带eyoucms内核,无需再下载eyou系统. 原创设计.手工书写DIV+CSS,完美兼容 ...

  2. c++模板---3(类模板碰到继承问题,类模板类外实现,类模板与友元函数)

    类模板碰到继承问题 基类如果是模板类,必须让子类告诉编译器 基类中的T到底是什么类型 如果不告诉,那么无法分配内存,编译不过 利用参数列表class Child :public Base<int ...

  3. C++ Primer 5th笔记(chap 16 模板和泛型编程) 类模板的成员函数

    1. 分类 1.1 定义在类模板内的成员函数 被隐式声明为内联函数. 1.2. 类模板外部的成员函数, 类模板的成员函数本身是一个普通函数.但是,类模板的每个实例都有其自己版本的成员函数.因此,类模板 ...

  4. C++ 类模板中友元函数问题

    #pragma once #include<iostream> template<typename T> class TestFriendTemplate { public:/ ...

  5. 问模板函数、函数模板,模板类、类模板的区别的问题?

    问模板函数.函数模板,模板类.类模板的区别的问题? - 赵保龙 - 博客园 问模板函数.函数模板,模板类.类模板的区别的问题? 在C++中有好几个这样的术语,但是我们很多时候用的并不正确,几乎是互相替 ...

  6. 类模板,多种类型的类模板,自定义类模板,类模板的默认类型,数组的模板实现,友元和类模板,友元函数,类模板与静态变量,类模板与普通类之间互相继承,类模板作为模板参数,类嵌套,类模板嵌套,类包装器

     1.第一个最简单的类模板案例 #include "mainwindow.h" #include <QApplication> #include <QPush ...

  7. C++11 lambda表达式、function类模板、bind函数适配器

    文章目录 lambda表达式 lambda表达式的语法 lambda表达式的原理 function模板 function与重载函数 bind函数适配器 lambda表达式 当我们在写代码的时候如果经常 ...

  8. C++ 泛型编程(一):模板基础:函数模板,类模板,模板原理,模板匹配规则

    类模板 函数模板 泛型编程 泛型编程,泛型即是指具有在多种数据类型上皆可操作的含义,其实就是能够帮助开发者编写完全一般化并可重复使用的算法,同样的工作不需要做多次,同样的算法针对不同的类型也不应该写多 ...

  9. C++ 泛型编程(一):模板基础:函数模板、类模板、模板推演成函数的机制、模板实例化、模板匹配规则

    文章目录 泛型编程 函数模板 函数模板实例化 隐式实例化 显式实例化 函数模板的匹配规则 类模板 类模板的实例化 泛型编程 泛型编程旨在削减重复工作,如: 将一个函数多次重载不如将他写成泛型. voi ...

  10. 泛型算法(lambda表达式、function类模板、bind函数适配器、迭代器类别、链表数据结构独有的算法)

    文章目录 概念 find()函数 迭代器令算法不依赖于容器 但算法依赖于元素类型的操作 算法永远不会执行容器的操作 只读算法 accumulate()函数 从两个序列中读取元素(equal函数为例) ...

最新文章

  1. Electron 调用系统工具记事本、计算器等
  2. 边缘数据中心2024年市场规模将超过130亿美元
  3. 生产力提升! 自己动手自定义Visual Studio 2019的 类创建模板,制作简易版Vsix安装包...
  4. Android之CheckBox复选框控件使用inelayout.xml Xml代码
  5. 【华为云技术分享】十分钟从入门到精通(下)——OBS权限配置
  6. php前台提交后台刷新,用js post数据后到后台,处理后如何实现前台页面刷新?...
  7. 使用Data URI Scheme优雅的实现前端导出csv
  8. ELK官方文档:在Kibana加密通讯
  9. swift中闭包的循环引用
  10. android分享到新浪微博,认证+发送微博,
  11. idea调试代码错误_通过调试进行指导:如何将代码错误转化为学习经验
  12. 支付业务与技术架构学习总结(9)——银行核心系统之清算体系
  13. 让计算机网络与作文教学,“基于计算机和网络环境下的写作教学研究”课题组  2015-2016学年度上学期研究计划...
  14. HashTab-查看哈希值小工具,一键插件文件md5值
  15. 修改网页视频播放速度
  16. 算法笔记:找考试座位号问题
  17. stem教育小学制度管理
  18. 关于一个ISE错误XST:899的错误判断的讨论
  19. surf算法原理-包你明白surf过程
  20. 剑网三账号分离能分到其他服务器,数据互通全面启动_剑侠情缘网络版叁_金山游戏官方网站_金山逍遥Xoyo.com...

热门文章

  1. zed_wrapper
  2. FFMPEG+SDL2 实现播放器功能
  3. Redis和Mysql数据同步的两种方案
  4. APP界面控件中英文名称汇总
  5. Processing 教程(7) - 平移、旋转、放缩
  6. ALE and EDI
  7. 2019,我是如何转向战略成功,并成功跑通一个现金流项目的
  8. Android AVD emulator模拟器获取root权限(4.1.2以下)
  9. DVWA——Command Injection
  10. 美剧 良医---读后感