2026/1/10 2:37:55
网站建设
项目流程
网站建设策划实训总结,大连本地网,自己做网站需要几个软件,标准百度网站建设闲谈#xff1a;上一篇初识模板我也只是初略了解#xff0c;这一次我在整理一下。模板模板是C支持泛型程序设计的工具#xff0c;通过它可以实现参数化多态性。参数化多态性#xff1a;就是将程序所处理的对象的类型参数化#xff0c;使得一段程序可以处理多种不同类型的对…闲谈上一篇初识模板我也只是初略了解这一次我在整理一下。模板模板是C支持泛型程序设计的工具通过它可以实现参数化多态性。参数化多态性就是将程序所处理的对象的类型参数化使得一段程序可以处理多种不同类型的对象。函数模板与重载、宏定义对比所解决的缺陷重载与函数模板函数模板与函数重载看起来大同小异但是重载的类不能传入与之相同类型的参数从而使得要多建几个代码框架相同的函数使程序代码冗余可读性降低。比如int max(int x,int y){…} float max(float x,float y){…}与之相似的还有宏定义宏定义只是在编译时进行简单的宏展开避开了类型检查机制容易产生隐藏错误。#define max(x,y) ((x)(y)?(x):(y)) max(a, b) //替换后((a)(b)?(a):(b))像这样我们调用max宏定义替换时a和b会产生多次自增而我们需要的只是一次自增函数模板模板可以轻松地解决上述问题减少隐式错误和减少代码冗余。还是以max举个例子template class T T max(T x, T y){ return x y ? x : y; }函数模板的使用函数模板的格式template class 形参名1class 形参名2......返回类型 函数名(参数列表) {函数体}以上面举例的max模板为例关键字template后面的尖括号表明max函数要用到一个叫做T的参数我们称作模板参数而这个参数是一种类型。该模板的含义就是无论参数T为int、char或其他数据类型包括类类型函数max的语意都是对x和y求最大值。这样定义的max代表了一类具有相同程序逻辑的函数称为函数模板。注意使用函数模板时一定要实例化,。原因:函数模板本身是不被编译器编译的必须使用实例化给模板T绑定类型后才能使用。完整使用template class T T max(T x, T y){ return x y ? x : y; } //一下是传入模板后编译器扩展结果 //double max(double x, double y) //{ return x y ? x : y; } int main( ){ double a 1.0, b2b1; b1 max(a, 2.0);//这里是隐式实例化b b2 maxdouble(a, 2.0)//显示实例化 return 0; }直接使用max()传参识函数模板接受了一个隐含的参数double。编译器自动将函数模板扩展成一个完整的关于double数据比较大小的函数然后再在函数模板被调用的地方产生合适的函数调用代码。显示调用就是我们手动转换了传参的类型。这里有个问题了既然要实例化才能使用模板那这里我就需要传入类型不同的参数咋办啊这里那就需要我们在模板里多写几条class T来分类传入类型了template class T1, class T2 auto max(T1 x, T2 y) { return x y ? x : y; } //一下是传入模板后编译器扩展结果 //传入res1 //double max(int x, double y) //{ return x y ? x : y; } //传入res2 //double max(int x, float y) //{ return x y ? x : y; } int main() { int a 10; double b 20.5; float c 15.8f; auto res1 max(a, b); cout int和double的最大值 res1 endl; auto res2 max(b, c); cout double和float的最大值 res2 endl; return 0; }当然我还是拿之前的例子举例这里返回值会被强制全部转换成double返回。但想传入不同类型参数大抵就是这样使用了。函数模板传入类类型的使用模板除了简单的传入类型我们也可以将自定义类型传入进去比如这样我定义有个学生类来比较class Student { public: string name; int score; Student(string n, int s) : name(n), score(s) {} }; template class T T max(T x, T y) { return x y ? x : y; } bool operator(const Student a, const Student b) { return a.score b.score; } int main() { Student s1(张三, 80); Student s2(李四, 90); Student s_max max(s1, s2); cout 成绩更高的学生 s_max.name 成绩 s_max.score endl; return 0; }当然了这里的“”肯定是比较不了我们自定义类型的所以我们要对此进行一次运算符重载。模板匹配策略还有个问题那就是如果出现了与函数模板相同的函数那该怎么办我怎么知道该调用谁就比如下面这例子template class T T max(T x, T y){ return x y ? x : y; } int max(int x, int y){ return x y ? x : y; } //char max(char x, char y){ // return x y ? x : y; // } int main( ){ int num1; char ch2; int num 200; // 超过char范围-128~127 long l 123456789L; double d 987654321.0; max(num,num); //调用max(int,int) max(ch,ch); //调用max(T,T)若char max没被注释优先调用char max max(num,ch); //调用max(int,int)char→int // max(num, a); //调用max(char,char )int→char。 //前提是没用int max(),否则会优先char转化成int。 max(l, d);//调用max(T,T)long→double return 0; }max模板和max类都满足条件编译器该怎么判定那就来看看匹配规则吧。在这里优先级从高到低分为四类1、完全匹配。当普通函数和模板都完全匹配时编译器优先选非模板的普通函数。如max(num,num)满足两个函数那就优先调用普通函数int max()。2、提升转换(char和short转换为int及float转换为double)完全匹配的优先级远高于需要转换优先调用和实例化完全匹配的函数。如max(ch,ch)模板完全匹配可以直接用完全匹配而普通函数还要将ch转换为int类型提升转换那就优先调用完全匹配的函数模板。max(num,ch)函数模板只能传入一个类型这里有两个类型不满足模板。只能将int隐式转换成char优先满足提升转换的转换没有才进行标准转换。传入int max()。3、标准转换(int转换为char及long转换为double)提升转换与标准转换同时出现提升转换的优先级大于标准匹配编译器优先调用满足提升匹配的函数。如被注释调的代码 max(num, a);在这里我们将int max()注释掉并且解开char max的注释函数模板只能传入一个类型这里有两个类型不满足模板。只能将int转化成char,完成标准转换。但注意的是max(l, d)可以完成long→double的转换从而使用模板函数。写到这时我发现个这里有一个小问题前面模板类型使用不是说了max可以隐式转化这里max(num,ch)中的ch不应该也被转化成int形了吗那不应该可以传入模板但实际 max(num,ch)根本传不进去那为啥 max(l, d)的long→double的转换可以传入模板以下为我总结个人理解这是因为int与char之间的类型转换有争议他既可以提升转换也可以标准转换于是编译器根本不做任何隐式转换类型推导T不一致直接失败。而long与double之间推导失败后编译器通过模板实参显式指定隐式的完成了匹配long→double的隐式转换并且不存在double→long逆方向认为逆方向是不合理的除非我们手动显示转换不然类型推导T只有long→double着一种情况。同理float→double也是一样他们只有标准转换和提升转换一种种情况。即使我们写了float max和long max编译器依然不会逆向转换主动调用模板函数。PS:这一段理解的我头要秃了这只是个人理解还请酌情参考和指出我的错误_4、用户定义的转换如类声明中定义的转换。用户自定义的比较复杂这里我在重写一个代码:template class T T max(T x, T y){ return x y ? x : y; } int max(int x, int y){ return x y ? x : y; } class MyClass { public: int val; MyClass(int v0) : val(v) {} operator int() const { return val; } bool operator(const MyClass o) const { return val o.val; } }; int main( ){ MyClass obj1(5), obj2(3); // 自定义类型对象 max(obj1, obj2);// 调用模板函数max(MyClass,MyClass) max(obj1, 10);// 调用普通int函数obj1→int 10(int)模板推导失败 return 0; }max(obj1, obj2)可以直接匹配模板完全匹配匹配int max需要转换类型。max(obj1, 10);种obj1和10的类型不同匹配模板失败只能转换obj1类型为int后匹配普通函数。虽然obj1可以通过operator int() const { return val; } 重写成int型但可惜模板推导阶段编译器根本不会主动用operator int() 做转换只 “机械” 推导实参的原始类型。