函数模板:泛型程序设计
算法实现时不指定具体要操作的数据的类型
泛型:算法实现一遍适用于多种数据结构
优势:减少重复代码的编写
函数模板的形式:
template <class 类型参数1,class 类型参数2,……>
返回值类型 模板名(形参表){
函数体
}
template <class T>
void Swap(T & x,T & y){
T tmp = x;
x = y;
y = tmp;
}
int main() {
int n = 1;
int m = 2;
Swap(n,m);
cout<<n<<" "<<m<<endl;
return 0;
}
函数模板可以重载,只要它们的形参表不同即可,例如以下两个模板是重载
template<class T1,class T2>
void print(T1 arg1,T2 arg2){}
template<class T>
void print(T arg1,T arg2){}
c++编译器遵循以下优先顺序:
1、先找参数完全匹配的普通函数(非由模板实例化而得的函数)
2、再找参数完全匹配的模板函数
3、再找实参经过自动类型转换后能够匹配的普通函数
4、上面的都找不到,则报错
注意:可以在函数模板中使用多个类型,来避免二义性。可以传两个相同类型的实参,也可以传不同类型的实参。
template <class T1,class T2>
void Swap(T1 & x,T2 & y){
T1 tmp = x;
x = (T1)y;
y = (T2)tmp;
}
int main() {
int n = 1;
doublem = 2;
Swap(n,m);
cout<<n<<" "<<m<<endl;
return 0;
}
类模板:
c++类模板的形式:
template<类型参数表>
class 类模板名{
成员函数和成员变量
};
类模板里的成员函数如在类模板外面定义时
template<类型参数表>
返回值类型 类模板名<类型参数名列表>::成员函数名(参数表){……}
类模板定义对象的写法:
类模板名<真实类型参数表> 对象名(构造函数实际参数表);
如果类模板有无参构造函数,那么也可以只写:
类模板名<真实类型参数表> 对象名;
template <class T1,class T2>
class Pair{
public:
T1 key;
T2 value;
Pair(T1 k,T2 v):key(k),value(v){};
bool operator<(const Pair<T1,T2> &p) const;
};
template <class T1,class T2>
bool Pair<T1,T2>::operator<(const Pair<T1, T2> &p) const {
}
int main() {
Pair<
string,
int> student(
"Tom",
15);
cout<<student.key<<" "<< student.value<<endl;
return 0;
}
使用类模板声明对象:
编译器由类模板生成类的过程叫类模板的实例化,编译器自动将具体的数据类型替换类模板中的类型参数,生成模板类的代码
由类模板实例化得到的类叫模板类
函数模板可以作为类模板的成员,但函数模板的类型参数和类模板的类型参数不能相同,否则编译器会报错。
类模板的参数声明中可以包括非类型参数
template<class T,int elementsNumber>
非类型参数:用来说明类模板中的属性
类型参数:用来说明类模板中的属性类型,成员操作的参数类型和返回值类型
类模板与继承:
1、类模板派生出类模板:
template <class T1,class T2>class A{};
template<class T1,class T2> class B:public A<T2,T1>{};
2、模板类派生出类模板:
template <class T1,class T2>class A{};
template<class T> class B:public A<int,double>{};
3、普通类派生出类模板:
class A{};
template <class T> class B:public A{};
4、模板类派生出普通类
template <class T1,class T2>class A{};
class B:public A<int,double>{};