我什么时候会收到 "overloaded definition needed" 错误?

When do I get "overloaded definition needed" error?

举个简单的例子:

#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() 调用会出现错误,即:

No definition for Display() that takes (int, int, int) found.

No definition for Display() that takes (double, double, double) found.

然后我将不得不重载 Display() 并添加接受适当参数的那些。

那么在什么情况下我会收到语法错误?为什么在这种情况下我没有收到错误消息?

因为值是隐式转换的。这也称为自动类型转换。字符是整数类型,因此它们像任何其他 int 一样被线程化 - 将 double 或 float 分配给 int 将截断该值。

这很常见,几乎我能想到的所有编程语言都这样做。

int 可以转换为 char 因为 Standard conversions/Integral convesions.

A prvalue of an integer type can be converted to a prvalue of another integer type. A prvalue of an unscoped enumeration type can be converted to a prvalue of an integer type.

整数类型的定义见Basic concepts/Fundamental types.

Types bool, char, char16_t, char32_t, wchar_t, and the signed and unsigned integer types are collectively called integral types. A synonym for integral type is integer type.


由于 Standard conversions/Floating-integral conversions.

A double 也可以转换为 char

A prvalue of a floating point type can be converted to a prvalue of an integer type. The conversion truncates; that is, the fractional part is discarded.

这就是 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 ''777777720'' [-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;
}

然后它不知道这些值是什么,所以它不会发出警告。

如果你真的想停止它,你可以添加一个需要 ints 的重载并删除它,这样它会导致编译器错误,如

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 chars 之外的任何错误。