泛型编程
主要技术:模板
分类:函数模板和类模板
函数模板
建立一个通用函数,其函数返回值类型和形参类型可以不具体指定,用一个虚拟的类型来代表
语法:
template<typename T>
函数声明或定义
template:声明创建模板
typename:表面后面的符号是一种函数类型,可以用class代替
T:通用的数据类型,名称可以替换,通常为大写
template<typename T>//声明一个模板,告诉编译器后面代码紧跟着的T不要报错,T是一个通用数据类型
//template<class T>也可
void myswap(T &a,T &b){
T tmp=a;
a=b;
b=tmp;
}
void test(){
int a=10,b=10;
//1.自动类型推导,数据类型T必须保持一致,比如下面都是int
myswap(a,b);
//2.显示指定
myswap<int>(a,b);
}
//模板必须要确定出T的数据类型
template<class T>
void func(){
}
void tets(){
func<int>();//此时必须显示给出一个数据类型才能使用
}
普通函数和函数模板的区别
- 普通函数可以发生自动类型转换(隐式类型转换)
- 函数模板如果使用自动类型推导,不会发生隐式类型转换
- 如果使用显示指定类型会发生隐式类型转换
普通函数和函数模板的调用规则
-
如果函数模板和普通函数都有实现,优先调用普通函数
-
可以通过空模板参数列表来强制调用函数模板
-
函数模板也可以发生重载
-
如果函数模板可以产生更好的匹配,优先调用函数模板
void myprint(int a,int b){ cout<<1<<endl; } template<class T> void myprint(int a,int b){ cout<<2<<endl; } void test(){ myprint<>(a,b);//强制调用函数模板 char c,d; myprint(c,d);//调用函数模板,虽然普通函数可以类型隐式转换,但麻烦 //如果函数模板可以产生更好的匹配,优先调用函数模板 }
具体化的函数模板
template<> bool mycompare(Person &a,Person &b){
if(......
}
类模板
template<class NameType,class AgeType>
class Person{
public:
NameType name;
AgeType age;
Person(NameType name,AgeType age){
this->name=name;
this->age=age;
}
}
void test(){
Person<string,int> p1("xx",99);
}
类模板和函数模板的区别
-
类模板没有自动类型推导
-
类模板在模板参数列表中可以有默认参数
template<class NameType,class AgeType=int>//年龄默认为int类型 class Person{ ... }
类模板中成员函数创建时机
普通类中的成员函数一开始就创建
类模板中的成员函数在调用时才创建
类模板对象做函数参数
template<class T1,class T2>//年龄默认为int类型
class Person{
...
}
//1.指定传入参数
void test1(Person<string,int>&p){
}
//2.参数模板化
template<class T1,class T2>
void test2(Person<T1,T2>&p){
cout<<"t1的类型"<<typeid(T1).name()<<endl;//
}
//3.整个类模板化
template<class T>
void test3(T &p){
}
类模板与继承
template<class T>
class base{
T m;
};
//1. 当子类继承的父类是一个类模板时,子类在声明的时候,要指定出父类中T的类型
class son1:public base<int>
{
};
//2. 如果不制定,编译器无法给子类分配内存
//3. 如果想灵活指定出父类中T的类型,子类也需要变为类模板
template<class T1,class T2>
class son2:public base<T2>{
T1 m2;
};
类模板成员函数类外实现
class Person{
Person();
void showPerson();
};
template<class T1,class T2>
Person<T1,T2>::Person(T1 name,T2 age){
}
类模板分文件编写
- 直接包含源文件
- 将.h和.cpp中的内容写到一起,后缀名改为.hpp