1、基本概念
所谓泛型编程:以独立于任何特定类型的方式编写代码。使用泛型程序时,我们需要提供具体程序实例所操作的类型或值。标准库的容器、迭代器和算法都是泛型编程的例子。每种容器(如:vector)都有单一的定义,但可以支持定义许多不同种类的vector,他们的区别在于所包含的元素类型。
模板是泛型编程的基础。
泛型编程与面向对象编程一样,都依赖于某种形式的多态性,面向对象编程依赖的多态性称为运行时多态性,泛型编程依赖的多态性称为编译时多态性或参数多态性。对于运行时多态性,只要使用基类的引用或指针,基类类型或派生类类型的对象就可以使用相同的代码。在泛型编程中,我们所编写的函数和类能够多态的用于跨越编译时不相关的类型。一个类和一个函数可以用来操纵多种类型的对象。
在C++中,模板是泛型编程的基础,模板是创建类或函数的蓝图或公式。如标准库定义了一个类模板vector,可以产生任意数量的特定类型的vector类,如vector<int>和vector<string>。
2、模板定义
1.举例
(1)int compare(const string &v1, const string &v2)
{
if(v1<v2) return -1;
if(v2<v1) return 1;
return 0;
}
(2)int compare(const int &v1, const int &v2)
{
if(v1<v2) return -1;
if(v2<v1) return 1;
return 0;
}
(3) int compare(const double &v1, const double &v2)
{
if(v1<v2) return -1;
if(v2<v1) return 1;
return 0;
}
我们可以用函数重载来实现不同类型的比较,但是观察可知,上述3个函数只有形参不同,函数体是相同的,我们可以用函数模板来实现任意类型数据的比较。不仅仅是3种类型,如果希望此函数用于未知类型,只能用函数模板了。
2、函数模板定义
函数模板是一个独立于类型的额函数,可作为一种方式,产生特定的函数版本。
template <typename T>
int compare(const T &v1, const T &v2)
{
if(v1<v2) return -1;
if(v2<v1) return 1;
return 0;
}
模板定义以关键字template开始,后接模板形参表,模板形参表是用尖括号扩住的一个或多个模板形参的列表,形参之间以逗号分隔。
模板形参表不能为空。
3 模板形参表
模板形参可以是表示类型的类型形参,也可以是表示常量表达式的非类型形参。
类型形参在关键字class或typename后面定义。非类型形参在类型说明符之后声明。
其中,在此,关键字class和typename没有区别。
4 使用函数模板
使用函数模板时,编译器会推断那个模板实参绑定到形参,一旦编译器确定了实际的模板实参,就称它例化了函数模板的一个实例。
用实参的类型推断出类型形参的类型。
如int a = 10; int b= 11;
compare(a, b);
变量a时int型,推出形参const T &v1中的T为int型,同理得到const T &v2中的形参为int。然后根据函数形参的类型推断出模板形参的类型,对应的typename T 中的T为int,然后把模板函数中所有的T都换做int。称为实例化了函数模板的一个实例。
5、 inline 函数模板
inline关键字要在模板形参表之后,返回类型之前,不能放在关键字template之前。如:
template <typename T> inline T min(const T&, const T&);
3、定义类模板
举个例子:
template <typename Type> class Queue
{
public:
Queue();
Type &front();
const Type &front() const;
void push(const Type &);
void pop();
bool empty() const;
private:
//.....
};
//成员函数的实现
template <typename Type> void Queue<Type>::push(const Type &v1)
{
//....
}
总结:
函数模板是建立算法库的基础。类模板是简历标准库容器和迭代器类型的基础。
模板和虚函数应该是不能掺杂在一起的。