我正在学习C ++中的函数重载,并遇到了这个问题:
void display(int a)
{
cout << "int" << endl;
}
void display(unsigned a)
{
cout << "unsigned" << endl;
}
int main()
{
int i = -2147483648;
cout << i << endl; //will display -2147483648
display(-2147483648);
}
根据我的理解,int
范围内给出的任何值(在我的情况下int
是4字节)将调用display(int)
,超出此范围的任何值都将是不明确的(因为编译器无法决定调用哪个函数)。它对int
值的完整范围有效,除了它的最小值,即-2147483648
,其中编译失败并出现错误
调用过载的
display(long int)
是模棱两可的
但是将相同的值带到int
并打印该值会得到2147483648
。我对这种行为感到困惑。
为什么只有在传递最负数时才会观察到这种行为? (如果short
与-32768
一起使用,行为是相同的 - 事实上,在任何情况下,负数和正数具有相同的二进制表示)
使用的编译器:g ++(GCC)4.8.5
这是一个非常微妙的错误。你所看到的是C ++中没有负整数文字的结果。如果我们看[lex.icon],我们得到一个整数字面,
整数字面 decimal-literal integer-suffixopt [...]
可以是小数字,
十进制文字: 非零数字 decimal-literal'opt数字
其中数字是[0-9]
,非零数字是[1-9]
,后缀par可以是u
,U
,l
,L
,ll
或LL
之一。这里没有任何地方包括-
作为十进制文字的一部分。
在§2.13.2中,我们还有:
整数文字是一个没有句点或指数部分的数字序列,可选地分隔单引号,在确定其值时将被忽略。整数文字可以具有指定其基数的前缀和指定其类型的后缀。数字序列的词汇第一个数字是最重要的。十进制整数文字(十进制)以0以外的数字开头,由一系列十进制数字组成。
(强调我的)
这意味着-
中的-2147483648
是一元operator -
。这意味着-2147483648
实际上被视为-1 * (2147483648)
。由于2147483648
对于你的int
来说太多了,所以它被提升为long int
,并且模糊性来自不匹配。
如果要以便携方式获取类型的最小值或最大值,可以使用:
std::numeric_limits<type>::min(); // or max()
表达式-2147483648
实际上是将-
算子应用于常数2147483648
。在您的平台上,int
无法存储2147483648
,它必须用更大的类型表示。因此,表达式-2147483648
不是推论为signed int
,而是更大的签名类型signed long int
。
由于您没有为long
提供重载,因此编译器必须在两个同样有效的重载之间进行选择。您的编译器应该发出有关模糊重载的编译器错误。