模版解决的问题是:用同一个模版来处理不同的类型要求,最典型的是输入不同类型的参数,得到对应类型的结果。当然了函数可以作为模版,解决的是同一个函数处理不通参数得到对应结果的问题,同样,类也可以作为模版,处理的就是同一个类的写法处理不通类中的类型。这样的类叫类模版,类模版可以继承一般的类,也可以继承其他模版。
1、通常的模版函数-一般用法:其实就是定义一个可以表达多个类型处理的函数,这里的多个类型其实就是这个模版函数中的变量类型呀,函数类型呀之类的。
首先定义模版:比如:一个求和的函数,有int ,long,double类型输入,提供的功能是一个求和的输出。那么这样的函数就可以先定义一个模版,然后再来具体实例的时候通过传入参数求不同类型的和。
使用的时候就是具体实例化这个模版函数,此时使用 result (2, 3) 这样的方式知名这个T的类型为int.比如下来。
#include < iostream>
using namespace std;
template < class T>
T result(T a, T b)
{
return a + b;
};
int main(void)
{
int a = 2,b = 3, int_result;
long c=4, d=5, long_result;
float e=1.6, f=2.5, float_result;
int_result = result< int >(a,b);
long_result = result< long>(c,d);
float_result = result< float>(e,f);
cout<<"int result is "<<int_result<<endl;
cout<<"long result is "<<long_result<<endl;
cout<<"float result is "<<float_result<<endl;
}
2、如果模版要特殊化,也就是说如果模版再某些情况下不按照模版定义的类型(指定到具体类型)进行运算,可以通过修改默认类型T的方式操作,但是函数命令还不变,这样就是C++的方便之处。具体做法就是下面这样的
#include < iostream>
using namespace std;
template < class T>
T result(T a, T b)
{
return a + b;
};
//这里就是函数模版特殊化
template < >
string result< string>(string s1, string s2)
{
return s1+s2;
}
int main(void)
{
int a = 2,b = 3, int_result;
long c=4, d=5, long_result;
float e=1.6, f=2.5, float_result;
int_result = result< int>(a,b);
long_result = result< long>(c,d);
float_result = result< float>(e,f); //这里的一般用法
cout<<"int result is "<<int_result<<endl;
cout<<"long result is "<<long_result<<endl;
cout<<"float result is "<<float_result<<endl;
string s1="zhangyi";
string s2="yangtao";
string s3 = result< string>(s1, s2); //这里用了特殊用法
cout<<"s3 = "<< s3<<endl;
}
3、当然了模版函数中的类型T,也不一定要全部是要通过T类型来指定,也可以在模版函数中指定具体的类型,比如可以在模版函数上这样定义T result(T a, int b, float c)这样的。
4、在具体使用模版函数的时候,不指定参数类型,比如result <>这样的方式,则说明在模版函数定义的时候已经指定来具体的类型,值得注意的是这种默认参数的类型的模版函数只是在 c++11上支持,所以在编译代码的的时候需要指定编译条件为-std=c++11;如g++ test.cc -o test -std=c++11
如template < typename T=int>
T result (T a, T b)
{
return a + b;
}
使用的时候就这样用:
int a = 2, b =3;
int rel;
rel = result< >(2,3); //这里就是无类型参数的使用例子
————————————————————
5、上面说的函数模版,下面我们来理解下类模版:一样的道理类模版定义的时候如:
#include < iostream>
using namespace std;
//这里定义一个类模版
template < class T>
class helloworld
{
public:
void add_zhangyi(T a, T b); //两个数据相加
T result(); //计算结果函数
helloworld(T i); //构造函数
void showresult(); //打印结果
private:
T d; //两个加数的和
T c; //对象初始化函数
T dateresult; //最终的结果
};
template < class T> //这里需要指明template模版
void helloworld< T>::add_zhangyi(T a, T b) //这里需要在hellworld类中指明< T>的方式
{
d = a+b;
};
template < class T>
T helloworld< T>::result()
{
dateresult = c+d; //纪录最终的结果
return c + d;
};
template < class T> //这里实现构造函数
helloworld< T>::helloworld(T i)
{
c = i; //对象初始化
};
template < class T> //显示函数的实现
void helloworld< T>::showresult()
{
cout<<”result is” << dateresult << endl;
};
int main(void)
{
helloworld< int> hw(1); //初始化一个对象,初始化值为内部的private c = 1 定义类的时候需要指定int类型
hw.add_zhangyi(2,3); //进行2+3操作
hw.result(); //将2+3的结果和起初的1相加得到最后的结果值
hw.showresult(); //显示最终的结果 ty
}
6、一个类模版可以从一个基类继承。也就说基类是一个一般的类定义,而一个新的类模版继承这个基类。比如一个基类:class AA;另一个类模版定义BB想继承这个类AA
template < class T>
class BB : public AA
{
public:
T add( T a, T b);
}
template < typename T>
T BB< T>::add(T a, T b)
{
return a +b;
}
7、基于上面6,其实一个类模版也可以继承另一个类模版,比如这里又要定义一个类CC,需要继承类模版BB。则
template < typenam T>
class CC :public BB < T>
{
public:
T show(T a, T b);
}
具体内部函数的实现这样处理:这里其实可以继承基模版内部的函数,当然也可以不继承,如果继承的话则可以通过该类的参数去初始化基类的参数,如果不跟基类的函数则就和普通的类模版实现函数一样
template < typename T>
class< T>::show(T a, T b):BB< T>::add(a, b)
{
Cout<<“ result is ”<< (a + b ) << endl;
}