C++支持泛型编程(Generic Programming)
算法不局限于某个特定类型,而能在多种类型数据上实现操作。
如何实现泛型编程?
将逻辑结构相同,但具体数据元素类型不同的数 据或对象的通用行为抽象为模板(template), 把数据类型作为参数传入模板,生成实例代码。
模板概述
模板用于把函数或类要处理的数据类型参数化,表现为参数的多态性。模板用于表达逻辑结构相同,且具体数据元素类型不同的数据对象的通用行为,从而使程序可以从逻辑结构上抽象,把被处理的对象类型作为参数传递。
函数模板
函数模板的基本原理是通过数据类型的参数化,将一组算法相同但所处理数据类型不同的重载函 数凝练成一个函数模板。编译时,再由编译器按照函数模板自动生成针对不同数据类型的重载函 数定义代码。函数模板可以用来创建一个通用功能的函数,以支持多种不同形参,进一步简化重载函数的函数体设计。
函数模板的定义:
template <类型参数列表>
函数类型 函数名(形式参数列表)
{
函数体;
}
函数模板实例:
#include<iostream>
using namespace std;
template<class T1>
T1 fun(T1 x,T1 y)
{
return x>y?x:y;
}
int main()
{
int a1=3,b1=7;
char a2[]="lin",b2[]="zixi";
float a3=4.87,b3=0.02;
cout<<"整数"<<endl;
cout<<fun(a1,b1)<<endl;
cout<<"字符"<<endl;
cout<<fun(a2,b2)<<endl;
cout<<"浮点数"<<endl;
cout<<fun(a3,b3)<<endl;
}
运行结果:
函数模板的编译原理
函数模板是具有类型参数的函数。类型参数是表示数 据类型的参数,可指代任意一种实际数据类型。编译 器在编译到函数模板调用语句时,根据位置对应关系 从实参数据类型推导出类型参数所指代的数据类型, 然后按照函数模板自动生成一个该类型的函数定义代 码。不同类型实参的函数模板调用语句将生成不同类型的重载函数。
函数模板的调用语句可以明确指明类型参数,如函数名<类型1,类型2...>(实参表)
示例:
#include<iostream>
using namespace std;
template<class T1,class T2>
T1 fun(T1 x,T2 y)
{
return (x+y);
}
int main()
{
int a=2;
char b='l';
cout<<fun<char,int>(b,a);
}
类模板
类模板使用户可以为类声明一种模式,使得类中的某些数据成员、成员函数的参数和返回值能取任意数据类型。类模板用于实现类所需数据的类型参数化。类模板在表示数据结构(如数组、二叉树和图等)时显得特别重要,这些数据结构的表示和算法不受所包含的元素类型的影响。
类模板的声明格式如下:
template 类型参数表
class 类名
{
类声明体;
};
// 类实现部分:所有类外定义的函数成员,必须按如下的语法形式将它们定义成函数模板
template <类型参数列表>
函数类型 类名<类型参数名列表> :: 函数名( 形式参数列表 )
{
函数体;
}
代码实例:
#include<iostream>
#include<string>
using namespace std;
template<class T>
class G
{
T cj;
T xj;
public:
G(T c,T x){cj=c;xj=x;}
T sum(){return (T)(cj+xj);}
};
int main()
{
int a,b;
double c,d;
string a1,b1;
cout<<"整数"<<endl;
cin>>a>>b;
G<int> g1(a,b);
cout<<"浮点数"<<endl;
cin>>c>>d;
G<double> g2(c,d);
cout<<"字符"<<endl;
cin>>a1>>b1;
G<string> g3(a1,b1);
cout<<endl<<g1.sum()<<endl<<g2.sum()<<endl<<g3.sum();
}
需要注意的是:使用类模板定义对象时需要明确给出类型参数所指代的实际数据类型。
类模板名<实际数据类型列表> 对象名1,对象名2......
运行结果: