这是我不理解的代码
#include<iostream>
using namespace std;
template <typename T>
T calc(T, T) { cout << "template calc" << endl; }
double calc(double, double) { cout << "ordinary calc" << endl; }
template <>
char calc<char>(char, char) { cout << "template specialisation calc" << endl; }
int main() {
int ival;
double dval;
float fd;
calc(0, ival); // calls the generic calc(T, T)
// the following all call calc(double, double)
calc(0.25, dval);
calc(0, fd);
calc(0, 'J');
calc('I', 'J'); // calls calc(char, char)
}
有5个函数调用calc,所以我会根据它们的位置将它们称为1) - 5)。
1)有道理。 0是整数,ival是整数,有意义的是调用calc(T,T)。虽然我觉得我的理由是错误的。毕竟,它们都是双打的,所以如果调用calc(double,double),那也是有意义的。所以在这里寻求澄清。
2)没有戏剧,都是双打,叫钙(双,双)。简单。
3)fd是一个浮点数。可以调用calc(T,T)或calc(double,double)。因为1)导致对calc(T,T)的调用,我会假设同样会在这里保持,因为我们再次有一个param为0,但是,这会调用calc(double,double)。所以这让我感到困惑,尤其是这与1)之间的区别
4)我的第一个想法是0是一个有效的字符,所以是'J',所以它调用calc(char,char)。它可以使用常见的整数类型调用calc(T,T)。但是没有,两个都错了,它叫做calc(double,double)。我对此非常困惑。对我毫无意义。
5)有意义,但只有我应用了与4)相同的逻辑,这在4)中是错误的,所以如果我要看到另一个使用模板的例子,我不确定是什么逻辑申请。
所以寻找解释为什么这个程序能做它的功能。
感谢。
答案 0 :(得分:1)
首先,当您在源代码中写入文字“0”时,它的类型为“int”。在查找要调用的函数时,编译器会选择最匹配的函数。如果不可用,编译器将执行一些隐式类型转换以使其工作。
1)0和ival都是int
2)对于double和double,calc(double,double)完全匹配
3)对于int和float,未找到匹配,因此两者都转换为double
4)对于int和char,与3)相同
5)对于char和char,calc(char,char)完全匹配
答案 1 :(得分:1)
我建议你阅读overload resolution:
选择最合适的重载函数或运算符的过程称为重载解析。
假设f是一个重载的函数名。当你打电话给 重载函数f(),编译器创建一组候选 功能。这组函数包括所有名为f的函数 可以从您调用f()的位置访问。编译器 可以包括作为候选函数的替代表示 其中一个名为f的可访问函数,以方便过载 分辨率。
创建一组候选函数后,编译器会创建一个 一套可行的功能。这组函数是其中的一个子集 候选职能。每个可行功能的参数数量 同意你用来调用f()的参数数量。
编译器选择最好的可行功能,即功能 声明C ++运行时环境将在您调用时使用 f(),来自可行功能集。编译器执行此操作 隐式转换序列。隐式转换序列是 转换函数中的参数所需的转换序列 调用函数中相应参数的类型 宣言。隐式转换序列排名;一些 隐式转换序列比其他转换序列更好。最好的可行 函数是其参数都更好或更好的函数 等级隐式转换序列比其他所有转换序列都要多 可行的功能。编译器不允许其中的程序 编译器能够找到多个最佳的可行功能。
1,2和5都是完全匹配,因此不需要转换。
要解释3和4,请注意,如果删除double, double
功能,您的程序将无法编译。这是因为3和4的模板参数cannot be deduced(因为参数类型不匹配)。因此,只有double, double
函数被视为候选函数。