模板&泛型编程

来源:互联网 发布:三维编程叫什么 编辑:程序博客网 时间:2024/05/16 05:32

           泛型编程:编写与类型无关的逻辑代码,是代码复用的一种手段。模板是泛型编程的基础。

      模板分为类模板和函数模板。函数模板代表了一个函数家族,该函数与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。

    

      如上例所示,就是一个简单加法函数的模板,typename是用来定义模板参数的关键字,也可以使用class,T代表着传入实参的类型,可以为int,float,double型。在这里要说明的是,模板是一个蓝图,它本身不是类或者函数,编译器用模板产生的类或者函数叫做特定类型版本,产生模板特定类型的过程称为函数模板的实例化。

      注意:

      1.当给定需要的函数,则编译时会调用给定的函数,若给出显示的实例化,则会调用模板。

      2.定义typedef int T时,优先使用模板参数列表中的T。

      3.所有模板形参前面必须加上class或者typename关键字修饰。

      4.在模板函数的内部不能指定缺省的模板实参。(类模板可以)

      实例化:

      隐式实例化:根据函数实参的类型去推演函数模板中的参数(实参推演)。

      显示实例化:不考虑函数的实参类型。

      模板函数在(隐式的)实例化时,不会进行参数的隐式类型转换,而是会产生新的实例。除了以下两种情况可以发生转化:

      ⑴const转换:可以将一个非const对象的引用或指针传递给一个const的引用(或指针)形参。

     

      这里,const T a,假如这里的T为int*,按照我们的一般想法则是替换为const int* a,这时的a为一个指向常量的指针,指针的指向可以修改,指针的内容不能修改,这样想是错的。T代表了一个整体,const永远修饰的是变量a,也就是说const T a就类似int* const a,这是一个常指针,自己的指向不能修改,但指向的内容可以改变。

      ⑵数组或函数到指针的转换:如果模板形参不是引用类型,则对数组或函数类型的实参应用常规指针转换,数组实参可以转换为一个指向其首元素的指针,函数实参可转换为一个该函数类型的指针。

    

    

           

    

      模板参数

     数模板有两种类型参数:模板参数和调用参数。

     模板形参分为了类型形参和非类型形参。模板形参的名字在同一模板形参列表中只是使用一次。

     下面是关于模板形参的说明

     1. 定义模板函数时,模板形参表不能为空。

     2.模板形参可以是类型形参,也可以是非类型形参,类型形参跟在class和typename后面。

     3.模板类型形参可作为类型说明符用在模板中任何地方,与内置类型或自定义类型使用方法完全相同,可用于指定函数的形参类型,返回值,局部变量和强制类型转换。

     4.模板形参表中,class和typename具有相同的含义,可以互换,使用typename更加直观,但关键字typename是作为C++标准假如C++中的,旧的编译器可能不支持。

     模板函数重载

     1.一个非模板函数可以和一个同名的函数同时存在,而且该函数模板还可以被实例化为这个非函数模板。

     2.对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好的匹配函数,那么将选择模板。

     3.显式指定一个空的模板实参列表,该语法告诉编译器才能来匹配这个调用,而且所有的模板实参都应该根据实参演绎出来。

     4.模板函数不允许自动类型转换,但普通函数可进行自动类型转换。

     模板函数特化

     特化:模板函数要先存在,特化函数返回值参数类型一致。

     函数模板特化形式如下:

   

       注意:特化不能出现在模板实例的调用之后,应该在头文件中包含模板特化的声明,然后使用该特化版本的每个源文件包含该头文件。下面我们来看一个比较字符串大小函数。

template<typename T>int Funtest(T p1, T p2){if (p1 > p2){return 1;}if (p1 < p2){return 2;}return 0;}template<>int Funtest<const char*>(const char* p1, const char* p2){return strcmp(p1, p2);}void test4(){char* str1 = "1234";char* str2 = "abcd";cout<<Funtest(str1, str2)<<endl;}
             模板类

       1.模板类与函数模板的区别

       编译器不能为类模板推演模板参数类型,所以,为了使用类模板,我们必须在模板名后的尖括号中提供额外的信息(显示模板实参列表),用来代替模板参数的模板实参列表。当一个类模板为其所有的模板参数都提供了默认实参,且我们希望可以使用这些默认参数,就必须在模板名后跟一个空尖括号。

       2.类模板成员函数的实例化

       如果一个成员函数没有被使用,则它不会被实例化。成员函数只有在被用到时才进行实例化,这一特性使得即使某种类型不能完全符合模板操作的要求,我们仍然能用该类型实例化类。

       3.在类模板类简化模板类名的使用

       当我们使用一个类模板时必须提供模板实参,但这一规则有一个例外,在类模板自己的作用域中,我们可以直接使用模板名而不提供实参。

       模板的优缺点小结:

       优点:模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库中(STL)因此而产生,增加了代码的灵活性。

       缺点:模板让代码变得凌乱复杂,不易维护,编译代码时间变长,出现模板编译错误时,错误信息非常凌乱,不易定位错误信息。 

0 0
原创粉丝点击