上次已经对模板和模板函数有了一些提及,在写一下这次内容前先对上次回顾一下。
模板:顾名思义是创造一个模具,在需要用到类似东西时使用模具创作,会比重新创作更快,更方便,对于我们来说,就是减少代码量和提高效率的工具。
它的关键字为template,比如我现在要写一个通用Add加法的函数,使用方式为:
template<typename T>
T Add(T a, T b)
{
return a + b;
}
T就是我在调用函数时输入参数的类型,如此就可以针对不同类型加法进行计算,比我们一个一个添加进行函数重载方便快捷很多,当然我们可以输入参数的类型和返回的类型都是由我们定的,我们也可以输入两个不同的类型,让他返回其中之一,或者我们给定的类型,比如:
template<typename T,template T1>
T Add(T a, T1 b)
{
return a + b;
}
这样我就生成了一个针对两个类型参数的加法,我让他返回第一个参数的类型,这种组合我们可以任意设定。这里面的typename可以使用class进行替换,作用是相同的。
上次我们同样也提到了如果调用函数时,代码里已经有可以调用的函数,则不会重新生成新的函数,因为模板函数在编译阶段不生成代码,但是如果你依然希望让模板来生成一个你需要的函数时,可以在调用函数时,在函数名后加上你需要特化的类型,比如Add<int>(1,2); 这样在调用时就会直接调用模板生成你所需要的函数,不会考虑此函数是否已经存在。
模板类
模板类同样也是模板,在需要使用时,同样需要使用template进行定义。
比如我们来实现一个动态的顺序表,定义格式如下:template<typename T>
class Seqlist
{
private:
T* data; //存放数据
int capacity; //容量
int size; //已存数据
};
这就是模板类的定义,函数什么的实现就不写出了。
模板类的特化
模板类在使用时必须进行特化,特化格式跟函数相同,比如我要生成一个整形的顺序表,代码为:Seqlist<int> s;
容器适配器:
使用容器,提供统一接口,不提供容器,也就是说,只提供函数,并不提供函数应用的对象
template<typename T>
class Seqlist //创造容器
{
private:
T* data;
int size;
int capacity;
};
template<class T, template<class> class Container = Seqlist> //实现容器适配器,template<class>表示
class stack // Container为一个模板类类型的模板形参
{ //这里就可以将Seqlist作为形参,相当于在顺序表基础上实现函数
public:
private:
Container<T> con;
};
上述为容器适配器实现过程,容器可以根据输入改变,而功能在适配器里构造。
有模板类适配器就有非模板适配器,实现方式相同,而适配器第二个参数改成你所需要的,不用模板方式输入。