泛型是许多语言中都存在的概念,它的出现主要源自于对不同类型数据进行相似处理的需求。
比如下面的add函数,分别用于对int,float类型进行相加。在c语言里需要用两个函数实现。
int add(int a, int b) {
return a + b;
}
float add(float a, float b) {
return a + b;
}
这样写虽然可以实现功能,但自己看起来也觉得很浪费,我们很自然地想要有一个函数,不管输入的数据类型是int还是float,我都可以把它们相加起来,只需要写一个函数。这就自然引出了泛型的概念。
下面看一下cpp中用泛型实现的add函数:
template <typename T>
T add(T a, T b) {
return a + b;
}
template <typename T>声明了一个template T(中文:模板,可以理解为泛型),然后紧接着声明了一个使用T的函数add。这个函数在c++里通常叫模板函数。
注意,声明泛型后接下来必须定义一个模板函数或模板类,即使不立刻写函数体,也必须要写一个函数声明。
// 声明模板
template <typename T>
// 必须定义一个模板函数或模板类,否则会导致编译错误
void exampleFunction(); // 仅声明,没有函数体
否则,template接下来的定义会被视为模板定义的一部分,比如下面的代码:
template <typename Type>
struct stct
{
int a;
int b;
};
结构体stct我们的本意是和泛型完全无关的一个结构体,但因为它紧接着定义在template后面,
所以会认为是泛型结构体,这种情况是不推荐的。有的编译器可能会给出错误,而有的则不会。
如果没有给出错误,那么在使用这个结构体时,必须给它传一个类型,随便什么类型都可以。
struct stct<float> s = {1,2};
std::cout << s.a << std::endl;
这里的类型名,int,float,经过我的尝试后都可以,但如果不传类型,则会报错:
incomplete type "stct" is not allowed
模板函数的使用。
模板函数的使用只需要在调用时提供具体类型即可。
int ret = add<int>(1,2);
float ret = add<float>(1.1,2.2);
这个就是c++中泛型在函数上的基本用法。