关于C++模板化
一、模板参数类型模板化
C++中的模板主要是函数模板和类模板。有些函数功能相同,但是数据类型不同,可也将其看做一类函数,可以使用函数模板来定义;有一些类所具有的函数成员的功能相同,但是仍然是数据类型不同,这是可以使用类模板对其进行定义。
我们可以从sort函数的第三个参数进一步理解。
sort(iter b,iter e,cmp)
这里的cmp可以是函数或者具有函数功能的类,即仿函数。比如我们定义升序排序。
template <typename T> bool cmp(const T&a, const T&b){ return a<b; };
或者使用仿函数
template <Typename T> struct cmp{ public: cmp(); bool operator()(const T&a,const T&b){ return a<b; } };
若为降序排列,和上面非常类似。
二、系数参数化
关于参数的模板化,典型的是C++中的count_if函数
count_if(iter b,iter e,cmp);
template <Typename T> struct cmp{ public: cmp(T num):num(num){} bool operator()(int i){ return i>num; } private: T num; }
调用可以这样
count_if(iter b,iter e,cmp(12))
模板可以检测到是整数类型的cmp函数实现
三、方法参数化
比如一个求取特征的系统,现在要使用多种求特征的算法,来求取特征,由于特征太多,于是将其分发给多个人来完成,每个人负责一类算法,如何在将这些算法整合到系统之后,系统的整体的代码不需要修改?这时可以使用方法参数化。
我们可以首先定义一个ExtractBase class
#include <vector>
using namespace std;
class ExtractBase{
public:
virtual vector<vector<double> > extract(vector<double> wav);
};
所有特征提取方法都继承自这个基类。
例如:
#include <vector> using namespace std; class f1:public ExtractBase{ public: vector<vector<double> > extract(vector<double> wav); }; class f2:public ExtractBase{ public: vector<vector<double> > extract(vector<double> wav); };
对他们的调用,就简化了,因为他们有共同的特征提取方法,并且都有基类。
template <extractf Fun> void extractAudio(vector<double> wav){ Fun fun; vector<vector<double> > feature = fun.extractr(wav); }
使用是这样的
extractAudio(v,f1)
extractAudio(v,f2)
这个方法不会关心是哪一种特征提取算法,因为他们都已经变成了模板,并且都有相同的特征提取接口。
有的同学,可能会有疑问,这里使用多态不就可以解决问题吗?有两个问题:
一、多态速度是问题
二、万一不能使用多态呢?????
四、参数模板简化
在模板的调用当中,我们有时发现一个问题,比如我们定义一个模板
template <class T,class t,class q> .....
但是我们发现T是一个自定义的类,里面有t类型和q类型的数据成员,也就是说,t和q的类型是和T的类型紧密关联在一起的,这是如何简化这个问题,从而在使用的时候只需要指定T即可。
那么我们需要学会使用类型成员。我们一般都知道C++类的两种成员:数据成员和函数成员。但是类型成员常常被忽略掉。什么是类型成员呢?类型成员可以看做是对类型的进一步封装,经过封装,新的类型名字,成为了这个类的一个成员。比如:
class Example{ public: typedef int INT; }
这时实际上INT是Example的一个类型成员。如何使用?
typename Example::INT a=12;
这时需要使用typename指定INT是这个类的一个类型成员不然会被误解为是一个数据成员。
有了这个知识点,这里的简化问题就好解决了。
假设T 类定义为如下: