今天编程遇到一个问题,使用重载会简单不少,但是如果输入类型不在预设的类型中,又会出现问题。使用模板又比较麻烦。
所以突发奇想,模板和普通函数同时使用的时候会怎么样?
比如如下代码:
int type(int){
return 0;
}
template<class T>
int type(T){
return 1;
}
本以为会报错,毕竟class T里是可以包含int的,但是没想到居然成功了。所以查了查,模板同样有重载。模板函数与非模板函数同样可以共存。主要规则如下:
-
当不指定模板参数列表的时候,模板与非模板,优先匹配非模板
就如同上面示例的代码,当执行如下代码的时候:cout << type(1) << endl; //0
返回值是0,也就是优先匹配了非模板函数。
-
当指定模板参数列表的时候,模板与非模板,匹配模板
还是上面示例的代码,当执行如下代码的时候:cout << type<int>(1) << endl; //1 cout << type<>(1) << endl; //1
返回值是1,也就是匹配了模板函数。也就是说,当我指定模板参数列表的时候,即使列表为空,也会优先匹配模板函数。
-
模板重载,优先匹配更准确的匹配
对于如下代码:template<class T> int type<T>{ return 0; } template<class T> int type<T*>{ return 1; }
当我执行:
char *ptr; cout << type(ptr) << endl;
返回值是什么呢?因为此时对于模板T,既可以指char,也可以指char*。
答案是,输出的是1。因为T*匹配的更精准(模板T匹配到的内容越少的越精准)。 -
特殊情况
对于如下代码:template<class T> int type<T>{ return 0; } template<class T> int type<T&>{ return 1; }
当我执行:
char ch; cout << type(ch) << endl; cout << type((char&)ch) << endl;
这次,感觉两个情况似乎一样精准。那么会调用哪个呢?
没错!答案就是…………报错;-D
你自己都分不清还能指望编译器分清楚?不存在的。
另外,调试的时候,当没有模板函数的时候,还遇见一些重载时基本数据类型的隐式转换,我也同样总结一波。
对于char、int、float、double、unsigned char、unsigned int、long long这几个类型而言:
- 首先,char和unsigned char优先转换为int型。其次转换为其他类型,但如果多个类型同时存在则会报错。(其实这里有点出乎我的意料,首先我以为char和unsigned char会互相转换,然后才是int,其次我以为unsigned int、long long int会和int同优先级)
- float优先转换为double,然后是其他类型。同优先级多个类型同时存在时报错。
- int、double、unsigned int、long long不分优先级
对于指针和数组:
- 不同类型指针之间可以互相转换,但是和其他基本类型不能互相转换。
- char*、char[]可以转换为string,但不能反过来。