以这个简单的例子为例:
#include <iostream>
using namespace std;
void Display(char a, char b, char c)
{
cout << a << " " << b << " " << c << endl;
}
int main()
{
Display(2, 3, 4); // Why no syntax error?
Display(2.0, 3.0, 4.0); // Also no error? O.o
Display('a', 'b', 'c');
system("pause");
return 0;
}
我期望在前两个Display()调用中出现错误,即:
未找到需要(int,int,int)的Display()定义。
未找到需要(双精度,双精度,双精度)的Display()定义。
然后我将不得不在其中重载Display()并添加接受正确参数的参数。
那么在什么情况下我实际上会收到语法错误?为什么在这种情况下我没有收到错误消息?
答案 0 :(得分:4)
由于Standard conversions/Integral convesions,int
可以转换为char
。
整数类型的prvalue可以转换为另一种整数类型的prvalue。可以将无作用域枚举类型的prvalue转换为整数类型的prvalue。
整数类型的定义可以在Basic concepts/Fundamental types看到。
类型
bool
,char
,char16_t
,char32_t
,wchar_t
和有符号和无符号整数类型统称为整数类型。整数类型的同义词是整数类型。
由于Standard conversions/Floating-integral conversions,double
也可以转换为char
。
浮点类型的prvalue可以转换为整数类型的prvalue。转换被截断;也就是说,小数部分将被丢弃。
答案 1 :(得分:4)
这就是C ++的工作方式。编译器将尝试将您提供给它的类型隐式转换为所需的类型,即使这是一个狭窄的转换(如果执行大括号初始化也会发生异常。您会得到一个错误)。在这种情况下,它将把您给它的int
转换为具有相同值的char
,然后继续。
由于您提供的所有值都是[0,127]范围内的编译时间常数,因此它永远不会失败,因此您甚至都不会收到警告,可能会溢出。
如果您使用过类似的方法
Display(2000, 32, 47);
您将收到来自GCC和Clang的警告,例如
GCC
main.cpp:12:12: warning: overflow in conversion from 'int' to 'char' changes value from '2000' to ''\37777777720'' [-Woverflow]
Display(2000, 32, 47);
Clang
main.cpp:12:12: warning: implicit conversion from 'int' to 'char' changes value from 2000 to -48 [-Wconstant-conversion]
Display(2000, 32, 47);
让您知道自己做的不好,但是只有知道值是什么,它才能这样做。如果有
int main()
{
int a, b, c;
std::cin >> a >> b >> c;
Display(a, b, c);
Display('a', 'b', 'c');
return 0;
}
然后它不知道值是什么,因此不会发出警告。
如果您真的想停止此操作,则可以添加一个需要int
的重载并将其删除,这样会导致类似编译器错误
void Display(char a, char b, char c)
{
cout << a << " " << b << " " << c << endl;
}
void Display(int, int, int) = delete;
int main()
{
int a, b, c;
std::cin >> a >> b >> c;
Display(a, b, c);
return 0;
}
错误:
prog.cc: In function 'int main()':
prog.cc:31:20: error: use of deleted function 'void Display(int, int, int)'
Display(a, b, c);
^
prog.cc:25:6: note: declared here
void Display(int, int, int) = delete;
您也可以全力以赴使用
template<typename T, typename U, typename V>
void Display(T, U, V) = delete;
,这将导致调用Display
而不是3个char
之外的任何错误。
答案 2 :(得分:0)
因为这些值是隐式转换的。这也称为自动类型转换。字符是整数类型,因此它们像其他任何int一样被线程化-为int分配double或float会截断该值。
这很常见,几乎所有我认为的编程语言都可以做到这一点。