
什么是模板 : 把类型当做未知量,可以忽略类型影响
什么是模板函数:被 template
template
templatevoid prrint(_Ty one){ }
也可以把他们写到同一行中,只不过不太美观
templatevoid prrint(_Ty one){ }
模板函数可以显式调用,也可以隐式调用。显式调用需要尖括号(< >)给_Ty未知类型赋予一个类型。隐式调用则会根据函数的参数来自动推段类型。
//显式调用 需要说明对应的类型 print(2).类的成员函数是模板函数(string("xxx")); //隐式调用 自动根据参数来判断类型 print("xxx");
class MM{
public:
MM() = default;
MM(string name,int age):name(name),age(age){
}
template
void print(_Ty one); //申明模板函数
protected:
string name;
int age;
};
//类外实现模板函数
template
void MM::print(_Ty one){
cout << one << endl;
}
int main(){
MM mm;
mm.print("ILoveYou");//显式调用类中的模板函数
mm.print(12); //隐式调用类中的模板函数
return 0;
}
(3).函数模板重载
1)普通函数被模板函数重载
模板函数可以和普通函数名重名。但这时候调用函数时到底调用的是普通函数,函数模板函数呢?
首先,通过显示调用,毫无疑问调用的是模板函数。但是通过隐式调用时,是优先调用普通函数,还是模板函数呢? 答案是优先调用普通函数(形参实参类型一致的情况下)
//模板函数 template2).模板函数被模板函数重载void print(_Ty one){ cout << one << endl; } //普通函数 void print(int one){ cout << one << endl; } int main(){ print ("xxx"); //毫无疑问调用模板函数 print(10); //调用普通函数 print("xxx"); //调用模板函数 reutrn 0; }
函数模板重载函数模板时,该调用哪个函数。应该优先调用类型相似度高的。
templatevoid print(_Ty1 one, _Ty2 two){ cout << one << endl; cout << two << endl; } template void print(_Ty one, _Ty two){ cout << one << endl; cout << two << endl; } int main(){ print(12,12); //优先调用一个类型的 print(12,"xx"); //优先调用两个类型的 print (12,12) //传入了两个参数给未知类型,所以一定调用的是两个类型的 return 0; }
2.模板类 (1).模板类创建
只要被template修饰就是一个模板类,不管有没有使用未知类型。template
而且,模板类必须显示调用 (类名<类型>)
templateclass MM{ public: protected: };
注:模板类不是一个完整的类,所以在使用到模板类的时候必须要 类名<类型> 配合使用, 尤其注意 模板类中成员函数 和 成员模板函数 类外实现的写法。
template(2).模板类继承class MM{ public: void print(); template void print(); protected: }; //模板类的成员函数类外实现 template void MM::<_Ty> print(){ } //模板类的成员模板函数类外实现 template template void MM<_Ty> print(){ } int main(){ MM m; //创建对象时 类名也要 写成 类名<类型>的形式 m.print(); reutrn 0; }
模板类的继承,子类也需要template修饰(代码举例一个普通类继承模板类)
template(3).模板类特化class MM { //只要被template修饰 就是模板类 不管有没有用未知类型 public: MM() = default; MM(string name) :name(name) { } void print(); protected: string name; }; //普通类继承模板类 template class Girl :public MM<_Ty> { public: Grit(string name) :MM<_Ty>(name) { } protected: };
用于处理一些自定义的特殊类型和折叠参数
1)局部特化
模板类n个类型特化成n-1个类型或者更少。 特化后的类,需要template<>修饰,且类名仍需要:类名<类型> 。特化后用到哪个未知类型,template中就写哪个未知类型。
类名<类型> 中, 类型的个数要和模板类一致。
//模板类 templateclass MM{ public: protected: }; //两个未知类型特化成一个类型 template class MM<_Ty,_Ty>{ public: protected: };
局部特化可以处理模板类不方便处理的自定义数据类型。
class Data{
public:
Data(int a,int b):a(a),b(b){}
void print(){
cout<
class MM{
public:
MM(_Ty1 one,_Ty2 two):one(one),two(two){};
void print(){
cout<
若是用 Data 类的对象来做上述模板类 MM 的未知类型。在不做运算符重载的情况下,是没有办法直接流运算符输出的。
但是我们通过局部特化,就可以通过 Data 类对象的 print() 方法来输出。
//局部特化来处理 Data 类的对象
template
class MM<_Ty,_Ty>{
public:
MM(_Ty one,_Ty two):one(one),two(two){}
void print(){
one.print();
two.print();
}
protected:
_Ty one;
_Ty two;
};
注:模板类也可以通过 Data 类对象的 print() 方法来输出,但是对于其他普通类型的数据就不适用了。相当于专门特殊化一个类,来处理特殊类型数据。
2)完全特化
完全特化 :模板类中已经没有未知类型了,都已经具体化了,但它仍是模板类。
需要template <> 修饰 ,但是已经没有未知类型了,所以尖括号中不用写类型,类名<类型>中,要写清楚所有的类型。
//完全特化
template <>
class MM {
public:
MM(string one, string two) :one(one), two(two) {}
void print() {
cout << one << " " << two << endl;
}
protected:
string one;
string two;
};
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)