持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第4天,点击查看活动详情
什么是模版
粗浅的理解,模版,其实就是和泛型一个意思。有时候我们希望用相同的方式处理不同的类型,使用模版可以避免重复编码。
但C++中的模版和Java等其他语言的泛型又有些区别。以函数模版为例,一个函数模版并不是一个函数,而是一种模式(pattern),一个图纸,或者说一个编译指令,必须确定了类型之后,才能实例化为一个函数,它才有函数地址。关于这一点,后面会有更详细的说明。
模版的语法
先来说说模版的语法
C++有类模版和函数模版,语法也类似。主要用到template 和 typename 两个关键字
// 函数模版
template <typename T> // typename 也可替换为class
void func(T t) {
...
}
// 类模版
template <typename T>
class A {
public:
void func(T t); // 成员函数声明
}
// 成员函数模版定义
template <typename T>
void A<T>::func(T t) { // 注意必须是 A<T> 不能是 A,因为A不是一个类
...
}
template开头,后面接类型列表,每种类型用typename或class开头。紧接着就是函数定义或者类定义。typename定义的类型可以在模版定义中当作普通类型来使用。
需要注意的是,在成员函数模版的定义中,要用A::func 而不是 A::func,这是因为前面说的,A是类模版,而模版只是一个pattern,并不是一个类,只有确定某一种类型之后,它才能实例化为一个类,所以A才代表一个类。
非类型模版参数
除了类型参数,模版中也可以包含值参数,例如:
template <typename T, int MAXSIZE>
class Stack {
private:
int arr[MAXSIZE];
...
}
既然已知是int类型,为什么还要通过模版参数来传递,而不通过构造函数来传递呢?对于函数模版也一样 ,为什么要通过模版参数而不是普通函数参数来传递值呢?
其实也很简单,上面的定义 int arr[MAXSIZE]中,要求数组长度MAXSIZE必须是编译期常量,而无论通过构造函数还是通过普通函数参数传递,都没办法限制只能传递编译器常量,所以编译会报错。