代码改变世界

C++模板和泛型编程

2012-01-03 14:27  马哈鱼  阅读(755)  评论(0编辑  收藏  举报

模板是泛型编程的基础。泛型编程就是以独立于任何类型的形式编写代码,使用泛型时,需要具体程序实例提供使用的类型或值。和面向对象一样,泛型编程也要依赖于某种形式的多态。在泛型编程中,我们所编写的类和函数能够多态地用于跨越编译时不相关的类型。一个类或一个函数可以用来操纵多种类型的对象。

模板定义
非类型模板形参:模板形参不必都是类型,在调用函数时非类型形参将用值代替,值的类型在模板形参表中指定。对模板的非类型形参而言,求值结果相同的表达式将认为是等价的。
编写模板时,代码不可能针对特定类型,但模板代码总是要对将使用的类型做一些假设。产生的程序是否合法,取决于函数中使用的操作以及所用类型支持的操作。编写模板代码时,对实参类型的要求尽可能少是很有益的。
编写泛型代码的两个重要原则:
(1)模板的形参是 const 引用:通过将形参设为 const 引用,就可以允许使用不允许复制的类型。大多数类型(包括内置类型和我们已使用过的除 IO 类型之外的所有标准库的类型)都允许复制。但是,也有不允许复制的类类型。将形参设为 const 引用,保证这种类型可以用于 compare 函数,而且,如果有比较大的对象调用 compare,则这个设计还可以使函数运行得更快。
(2)函数体中的测试只用 < 比较: 可以减少对可用于 compare 函数的类型的要求,这些类型必须支持 <,但不必支持 >。

模板编译时错误检查
(1)第一阶段是编译模板定义本身时。在这个阶段中编译器一般不能发现许多错误,可以检测到诸如漏掉分号或变量名拼写错误一类的语法错误。
(2)第二个错误检测时间是在编译器见到模板的使用时。在这个阶段,编译器仍没有很多检查可做。对于函数模板的调用,许多编译器只检查实参的数目和类型是否恰当,编译器可以检测到实参太多或太少,也可以检测到假定类型相同的两个实参是否真地类型相同。对于类模板,编译器可以检测提供的模板实参的正确数目。
(3)产生错误的第三个时间是在实例化的时候,只有在这个时候可以发现类型相关的错误。

实例化
类模板在引用实际模板类类型时实例化,函数模板在调用它或用它对函数指针进行初始化或赋值时实例化。

模板实参推断
从函数实参确定模板实参的值和类型的过程叫做模板实参推断。模板类型形参可以用作一个以上函数形参的类型。在这种情况下,模板类型推断必须为每个对应的函数实参产生相同的模板实参类型。如果推断的类型不匹配,则调用将会出错。

模板实参推断和函数指针
可以使用函数模板对函数指针进行初始化或赋值,这样做的时候,编译器使用指针的类型实例化具有适当模板实参的模板版本。

函数模板的显式实参
在某些情况下,不可能推断模板实参的类型。当函数的返回类型必须与形参表中所用的所有类型都不同时,最常出现这一问题。在这种情况下,有必要覆盖模板实参推断机制,并显式指定为模板形参所用的类型或值。