让源代码说明一切:
MLine::MLine(int x1, int y1, int x2, int y2)
{
}
MLine::MLine(double x1, double y1, double x2, double y2)
{
}
void __fastcall TVctDiag2::PrepareArrowTail(int x, int y)
{
double length_x1;
double length_y1;
MLine *line = new MLine(x, y, x - length_x1, y - length_y1);
}
编译器生成以下错误:
E2015 shapes.h上的'MLine :: MLine(int,int,int,int)在shapes.h:100'和'MLine :: MLine(double,double,double,double)之间的歧义。 / p>
我可以通过以下显式转换来解决此问题:
MLine *line = new MLine((double)x, (double)y, x - length_x1, y - length_y1);
部分施法是不够的:
MLine *line = new MLine((double)x, y, x - length_x1, y - length_y1);
我对表达式中隐式转换的规则感到很困惑。有人可以解释这种行为吗?表达式'x - length_x1'和'y - length_y1'的数据类型是什么?
答案 0 :(得分:2)
我对表达式中隐式转换的规则感到很困惑。有人可以解释这种行为吗?
二元运算符(+ - * / etc)处理相同类型的操作数(并返回与其操作数相同类型的结果)。如果类型不相同,那么将提升一个(通常但有时两个),以便两个操作数具有相同的类型。
表达式'x - length_x1'和'y - length_y1'的数据类型是什么?
X => int
length_x1 => double
所以类型不一样。因此将推广一个对象。在这种情况下,X将被提升为double(为什么要查找promotion rules)。操作员 - 将被应用,结果是双倍。
如果我们现在看看你的表达:
MLine *line = new MLine(x, y, x - length_x1, y - length_y1);
如果我现在用它们的类型替换子表达式:
MLine *line = new MLine(<int>, <int>, <double>, <double>);
您现在可以看到编译器的困境。它无法知道选择哪个版本的构造函数(两者都可以通过应用一轮投射来实现)。所以它必须产生错误。
答案 1 :(得分:1)
MLine *line = new MLine((double)x, y, x - length_x1, y - length_y1);
这不起作用的原因是因为派生的类型是:
MLine(double, int, double, double)
这是因为......
在具有混合操作数的操作中,操作数可能会转换为其他类型。对于浮点类型与整数类型的操作,首先将整数转换为浮点类型:
float f; int i;
f + i;
f + i
的类型为float
,因为在添加之前,i
会转换为float
。
此促销活动导致......
没有完全匹配,并且重载候选是不明确的。
从技术上(和简化),C ++编译器将使用完全匹配,或从一组重载候选中选择最佳匹配。这些规则并不重要(一个衡量标准是所需的转换次数)。
让我举一些例子:
void foo (int) {}
int main () { foo(5.f); }
- &GT; Works,因为只有一个候选者,而double可以隐式转换为int。
#include <iostream>
void foo (int) { std::cout << "foo(int)\n"; }
void foo (float) { std::cout << "foo(float)\n"; }
int main () { foo(5.f); }
- &GT;使用第二个版本,因为它完全匹配。
#include <iostream>
void foo (int) { std::cout << "foo(int)\n"; }
void foo (float) { std::cout << "foo(float)\n"; }
int main () { foo(5.); }
- &GT;注意:这次,我们传递double
。它不会编译,因为两个重载都需要转换,不是完全匹配,因此,候选是不明确的。
多个参数相同:
#include <iostream>
void foo (int,int) { std::cout << "foo(int,int)\n"; }
void foo (float,float) { std::cout << "foo(float,float)\n"; }
int main () {
foo(5.f, 5.f); // exact match with the (float,float) overload
foo (5, 5); // exact match with the (int,int) overload
foo (5, 5.f); // No exact match, and candidates are ambiguous
}