『c++』 模板(template)--- 参数化多态性

---恢复内容开始---

题外话:

  模板机制的设计和细节是由Bjarne Stroustrup在其1988年10月发表的名为“Parameterized Types for C++”一文中披露的。

引入:

  假设有两个类

  『c++』 模板(template)--- 参数化多态性

 它们的结构完全相同,差别就是数据类型int与double,因此我们可以引入下图结构表示:

『c++』 模板(template)--- 参数化多态性

『c++』 模板(template)--- 参数化多态性

在建立对象时用实参int或double代入形参T即可,这种做法成为参数化,即是将数据类型作为参数传递,用以替代形参T的实参可以是预定义数据类型或用户自定义数据类型(主要是类的对象),这是参数化的多态性。

详解:

一  函数模板 

  『c++』 模板(template)--- 参数化多态性

   上图定义了函数模板,主函数建立了三个模板函数,其中sq(i)使用 int 类型将类型形参 T实例化,sq(l)使用 long 型使形参T实例化,sq(5.55)则是double型。

  由此可见,在函数模板中使用类型参数 T 作为形参,这不是具体函数而是函数的抽象。等到进行实例化,即代入具体类型实参例如int、double等以后,就建立了具体函数,被称为模板函数。

二,函数模板的重载

 『c++』 模板(template)--- 参数化多态性

由结果明显可以看出,max(i,j),max(d,f),max(ch,hc)重载的为模板函数,max(d,j),max(i,d),max(ch,f)则调用的重载函数,注意下max(i,j),i,j同为int类型,max(d,f),d,f同为double型,ch,hc则同为char,我们返回查看函数并未发现与之相匹的重载函数,而max(d,j),max(i,d),我们在找到了与其匹配的重载函数,其恰巧也是调用的相应重载函数,但对于max(ch,f),ch为char类型,f为double的类型,首先程序中没有与之匹配的重载函数,也无匹配的函数模板,肿么办?程序显示了其调用了void max(int a, double b),我们不禁疑惑,为什么它不调用void max(double b, int a),而偏偏调用前一个函数,细观察另个函数的形式参数,不难发现void max(int a, double b),第二个形式参数为double类型,与f为同一类型,相比void max(double b, int a)更为接近,为什么会这样呢?查看调用的规则,我们会发现在混合使用重载的函数和模板时,应当避免二义性。此时它们的调用顺序是:

1.先调用匹配的重载函数

2.      如无匹配的重载函数,则调用匹配的函数模板。如果找到,则将其实例化,建立一个模板函数

3.      如再匹配不上,则调用相近的重载函数,此时可能丢失精度。

因此,可粗略地归纳为:先重载,再模板,后相近。

三 重载函数与函数模板都属于多态性机制,它们的区别如下:

(1)主函数调用重载函数和模板函数的格式完全相同。

  重载函数的优点是能够对不同数据类型使用不同程序逻辑进行类似操作。例如用于求取int或double的最大值的程序逻辑和操作就和求取char或char*的最大值的程序逻辑和操作差别很大。而函数模板无法处理。

  如果每种数据类型的程序逻辑和操作相同,则使用函数模板将会更加简洁和方便。

  模板是一种代码产生机制。

(2)对于重载函数,无论它们使用与否,全部都存于代码区中,都占用空间。

而对于函数模板,只当使用一个具体参数类型时才建立一个模板函数,而当使用另一个具体参数类型时再建立另一个模板函数。编程方便,使用灵活,效率较高。

---恢复内容结束---

上一篇:记录请求的耗时(拦截器、过滤器、aspect)


下一篇:Java 反射的应用