我正在参加「掘金·启航计划」。
1. 函数模板
将功能相同、类型不同的函数(类)的类型抽象成虚拟的类型。当调用函数(类实例化对象)的时候,编译器自动讲虚拟的类型具体化,这就是函数模版(类模版)。
- 模板关键字
template - T只能对当前函数有效,如下代码
//普通函数
void swapAll(T &a, T &b){
T temp = a;
a = b;
b = temp;
return;
}
//函数模板
template<typename T>
void swapAll(T &a, T &b){
T temp = a;
a = b;
b = temp;
return;
}
- 函数模板和普通函数都识别,会优先选择普通函数。可以加
<>强制调用函数模板。 - 函数模板自动推导时不能对函数的参数进行自动类型转换。比如下面这段代码,函数模板识别不了,就会调用普通函数。当然也可以显式强制用模版函数
swapAll<int>(10,'c');
int main() {
swapAll(10,'c'); //自动推出T为int类型,完成int类型交换
return 0;
}
当函数模板 推导出T为数组或其他自定义类型数据时可能导致运算符不识别,比如cout << 不知道怎么输出。
函数模板具体化:
template<> void swapAll<int>(Person &a, Person &b){
//...
return;
}
函数模板会编译两次:第一次,对函数模板本身编译;第二次,函数调用处将T的类型具体化。函数模版目标:模版为了实现泛型,可以减轻编程的工作量,增强函数的重用性。
2. 类模板
类模板和函数模板类似,对当前类有效。类模版的定义:
template<class T1, class T2>
class Data{
private:
T1 a;
T2 b;
public:
Data(){}
Data(T1 a, T2 b){
this->a = a;
this->b = b;
}
void showData(){
std::cout << a << " " << b << std::endl;
}
};
- 类模版实例化对象 不能自动推导类型。
为什么呢?就上述代码而言,如果我们直接
Data ob(10,20);按理说会推出T1、T2是int类型,但是如果Data ob;这样呢,无参构造就没有参数,不能推出T1、T2是什么类型。所有类模版就不支持自动推导类型。正确的写法应该是Data<int, int> ob(10,20);
类模板成员函数在类外实现,代码如下
template<class T1, class T2>
class Data{
private:
T1 a;
T2 b;
public:
Data(){}
Data(T1 a, T2 b);
void showData();
};
template<class T1, class T2>
Data<T1, T2>::Data(T1 a, T2 b){
this->a = a;
this->b = b;
}
template<class T1, class T2>
void Data<T1, T2>::showData(){
std::cout << a << " " << b << std::endl;
}
- 因为template只对当前类有效,所以在外部实现成员函数的时候也是需要重写template的。
- 类模版建议用hpp文件,h+cpp。类模版不能做h和cpp分离。
除了上面提到的,还有函数模版做友元,普通函数做友元。