理论科技的研究始终追求一种统一化,无论是如今数学代数领域的研究,已经转向代数结构的研究,而分析领域泛函的研究,再或是整个数学体系的公理化,无疑不是在向着一般化,统一化发展。
而这种现象落实到C++上也并不是毫无踪影,从类和对象的提出,正是一种将一类具有相同属性的对象一般化的过程。但是类的提出还不够,绝大多数的问题还不能得到很好的解决。例如,形参类型不同而函数体完全相同的函数实现起来的繁琐,形参类型不同而类的实现完全相同也十分繁琐。
这些问题最后都要归结到——对函数的一般化,类的一般化,而这正是我们今天的主题——模板类。C++为了解决上面的问题,提出了函数模板和类模板,统称为模板类。
一、函数模板
void Swap(int& x, int& y)
{
int tmp = x;
x = y;
y = tmp;
}
相信很多读者都写过交换函数,但是一般我们实现的都是int的交换,至多是char的交换。而现在如果提出要求,要求交换double,交换long,甚至是交换两个类对象,这时我们要重复的写好几个函数,但是它们仅仅是形参的改变。
为了减少这种繁琐重复的工作,要做的就是设计一种通用的函数,它可以接收所有类型的形参类型。而将这种工作交给编译器,是最好的选择,让机器做重复的工作正是提高我们效率的关键。
为此C++提出了函数模板,在函数的头顶上声明模板和模板类型。
template<typename T1,typename T2,.....>其中形如T1,T2的是通用化的虚拟参数。
有了它,函数的就可以改变成这样。
template<typename T>
void Swap(T& x, T& y)
{
T tmp = x;
x = y;
y = tmp;
}
这样形参类型的位置就全部被替换掉了,这个函数就是函数模板了,它可以接收任意类型的参数。
template<typename T>
void Swap(T& x, T& y)
{
T tmp = x;
x = y;
y = tmp;
}
int main()
{
int a = 2, b = 3;
double c = 3.2, d = 4.8;
Swap(a, b);
cout << a << " " << b << endl;
Swap(c, d);
cout << c << " " << d << endl;
return 0;
}
结果是正确的,说明它确实可以接收不同类型的参数。那我们就要问了,编译器在背后做了些什么?
编译器在接收到参数后会识别参数的类型,从而用模板实例化出一个对应的函数,这是很好理解的。
所以说我们对于两个不同类型的变量交换是不能通过这种方式实现的,因为会引起冲突,编译器识别的时候不知道T到底是两个类型中的哪一个, 但一般我们也不推荐这么做。
但处理这种方式也是可以的,笔者在这为各位介绍三种方法。
二、隐式实例化,显式实例化。
第一种的方法,使我们直接强转实参的类型,称为隐式实例化。这种方法,在swap函数下无法展示。我们简单实现一个加法函数。
template<typename T>
T Add(T& x, T& y)
{
return x + y;
}
不失一般性,我们将a变量的类型强转为double,但是注意,类型的转换实际上都会生成一个拷贝,拷贝是具有常量属性的,但我们的函数是接收不到常量的,为此必须在形参上加上const。
template<typename T>
T Add(const T& x, const T& y)
{
return x + y;
}
int main()
{
int a = 2, b = 3;
double c = 3.2, d = 4.8;
Add((double)a, c); //隐式实例化
return 0;
}
我们将结果打印出来,是可行的,感兴趣的读者可以尝试将c强转为int,再打印。
第二种方法是显式实例化,在函数调用的时候,在函数名后面加尖括号,里面写上参数的类型,这样就显式地告诉了编译器模板函数的参数类型。
int main()
{
int a = 2, b = 3;
double c = 3.2, d = 4.8;
cout << Add<int>(a, c) << endl; //显式实例化
return 0;
}
第三种方法是写两个模板参数,
template<typename T1,typename T2>//写两个模板参数,编译器也会自动匹配
T1 Add(const T1& x, const T2& y)
{
return x + y;
}
int main()
{
int a = 2, b = 3;
double c = 3.2, d = 4.8;
cout << Add<int>(a, c) << endl;
cout << Add(a, c) << endl;
return 0;
}
通过上面的介绍,可以看出模板的作用还是十分强大的,通用化的设计免去了繁琐的工作,希望读者能好好体会,本次的分享到此结束啦!