今天面一家独角兽公司的时候,被面试官问到这个问题。所幸之前的C++基础还记得一些,基本回答上来了。于是写一个blog来强化一下。
函数模板实际上,解决了一个函数多态性过程中所遇到的问题。实际上主要解决的就是形参类型不一的问题。
因为C++是一种静态语言,不像Python那样数据类型等运行起来了再确定,我们用函数或者用变量都必须确定类型。函数需要确定返回值类型,这就使得函数在使用起来不太灵活。
我们来比较C++和python在同一个函数的表现,打个比方,求最大值。
对于Python:
def max(a, b):
return a if a>=b else b
对于C++:
int max(int a, int b){
if(a>=b) return a;
else return b;
}
看出差别吗,差别就在于C++的函数确定了形参和返回值类型为int,输入两个浮点数这个函数就会报错,比如max(1.0, 2.0)。对于简便的动态语言Python来讲,就不会存在这个问题。那怎么解决C++的这个问题呢?
可以用函数重载。但还不是那么方便,咱们要定义好多种类型的函数才能cover掉python用一个函数解决的,打个比方:
int max(int a, int b){
if(a>=b) return a;
else return b;
}
double max(double a, double b){
if(a>=b) return a;
else return b;
}
float max(float a, float b){
if(a>=b) return a;
else return b;
}
...
仅因为类型不同,我们就定义这么多相同函数体的函数,而且还覆盖不了所有的情况,这确实是非常不方便的。
C++函数模板的出现,就巧妙解决了这个问题:
<template typename T>
T max(T a, T b){
if(a>=b) return a;
else return b;
}
咱不需要确定a和b的类型,我们先定义了一个类型T,这就是一个模板,T在这里占个坑,以后要什么类型就可以往里面填什么类型。我们同时可以确定多个不同的模板类型,来代表形参之间类型的不同。比如,我要比较一个int类型的数和一个double类型的数,哪个更大。上述模板就不能用了,因为上述模板默认两个形参的类型是一样的。不过,template还是挺灵活的,可以设置多个模板类型,比如:
<template typename T1,typename T2>
T1 max(T1 a, T2 b){
if(a>=b) return a;
else return b;
}
同时,我们的关键字typename可以完全被class代替,不过通常会建议优先用typename。
类模板只是函数模板的一个扩展,即含有用了函数模板的成员方法或用了含有类型模板的类成员。其实,也没有什么函数模板,我们的模板只是类型模板,用在函数里,这个函数就变成了"函数模板",用在类里,这个类就变成了"类模板"。来看一个栗子:
template <typename T>
class Complex{
public: //构造函数
Complex(T a, T b) {
this->a = a;
this->b = b;
}
private:
T a;
T b;
};
如上,Test类里面的类成员,并没有固定它的类型。我们是暂时用T来占坑,这样就给类的实例化留下了很大的空间。我们可以看一下实例化的实现:
int main() {
//对象的定义,必须声明模板类型,因为要分配内容
Complex<int> A(10, 20),*pa;
Complex<double> B(20.0, 30.0), *pb;
pa = &A;
pb = &B;
cout << pa->a << endl;
cout << pb->a << endl;
system("pause");
return 0;
}
就是这么简单,看很多blog都写得那么复杂~~