C++ 模板函数 讲解及实现
模板函数:机制介绍
在很多时候,我们需要对不同的数据类型做一些操作,但是这些操作是相同的,比如求取一个数组中的最大元素,我们只需:
for(int i=0; i<arr.size(); i++) if(arr[i] > max_val) max_val = arr[i];
可是面对不同的数据类型,我们需要实现不同的函数,比如下面我们需要实现两个函数来选择int或者double数组中的最大值,非常麻烦
int array_max(vector<int> arr) { int max_val = arr[0]; for(int i=0; i<arr.size(); i++) if(arr[i] > max_val) max_val = arr[i]; return max_val; } double array_max(vector<double> arr) { double max_val = arr[0]; for(int i=0; i<arr.size(); i++) if(arr[i] > max_val) max_val = arr[i]; return max_val; }
而模板函数机制则提供了一种灵活的组织方式,我们不需要告诉函数具体的形参数据类型,而只用专注于函数功能的实现
注意:在python中这种机制被很好的执行,如下是python的数组求最大:
def array_max(arr): val = arr[0] for item in arr: if item > val: val = item return val
你看,任何数据类型,只要支持[]下标运算和>比较运算,都可以使用这个函数,这就是【模板函数】机制在python理解下的实现
模板函数:实现
在实现函数之前,添加关键词:template<class 类型> 比如下面这个例子,可实现传入任意支持 ++ 运算的数据类型(包括重载了++算符的自定义数据类型),并且对其++
可以简单的认为:T就是传入数据类型的别名,真正执行的时候,会把T换成传入的数据类型,比如传入int,那么所有的T替换成int
template<class T> T add(T data) { data++; return data; }
多个同类形参:比如我们实现交换函数swap,交换两个同类型的变量
template<class T> void my_swap(T& o1, T& o2) { T temp = o1; o1 = o2; o2 = temp; }
多类型多变量:template内容必须按照形参表顺序,比如我们定义函数my_print来输出两种不同类型的变量
template<class T1, class T2> void my_print(T1 o1, T2 o2) { cout<<o1<<" "<<o2<<endl; }
值得注意的是,template<>里面的内容必须和函数的形参表完全一一对应,因为编译器会按实际调用时传入的数据类型,一一对应他们的别名
错误示范:
template<class T1, class T2, class T3> void add_dif(T2 a, T3 b, T1 aaa) { } // main函数: add_dif(1.23, 4.77, 1); // 编译器抛出错误: [Error] in passing argument 1 of void add_dif(T2, T3, T1) [with T1 = int; T2 = double; T3 = double]
正确写法:
template<class T1, class T2, class T3> void add_dif(T1 a, T2 b, T3 aaa) { }
注意如果函数返回值要返回模板类型T的数据,那么也要在形参表中添加T,即使函数没有用到,但为了编译通过并且顺利建立别名映射,必须添加
代码
首先使用模板函数add,将任意数据类型++后输出 然后使用模板函数my_swap交换两个任意的同类数据 然后使用模板函数my_print打印两个任意的数据类型(可不同也可相同)
#include <bits/stdc++.h> using namespace std; template<class T> T add(T data) { data++; return data; } template<class T> void my_swap(T& o1, T& o2) { T temp = o1; o1 = o2; o2 = temp; } template<class T1, class T2> void my_print(T1 o1, T2 o2) { cout<<o1<<" "<<o2<<endl; } int main() { cout<<add(114)<<endl; cout<<add(123.45)<<endl; cout<<add(a)<<endl<<endl; string s1="world", s2="hello"; my_swap(s1, s2); cout<<s1<<" -- "<<s2<<endl<<endl; my_print(123, "zsbd"); return 0; }