Когда я получаю ошибку "Требуется перегруженное определение"? - PullRequest
2 голосов
/ 28 марта 2019

Возьмите этот простой пример:

#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 (), которые бы говорили:

Нет определения для Display (), котороеберет (int, int, int) найдено.

Нет определения для Display (), которое принимает (double, double, double) найдено.

Где тогда мне пришлось бы перегрузить Display() и добавьте те, которые принимают правильные параметры.

Так в каких случаях я получаю синтаксическую ошибку?И почему я не получил ошибку в этом случае?

Ответы [ 3 ]

4 голосов
/ 28 марта 2019

int можно преобразовать в char из-за Стандартные преобразования / Интегральные конвекции .

Значение типа целого может быть преобразовано в значение другого целого типа. Значение типа нумерации с незаданной областью может быть преобразовано в значение типа целого числа.

Определение целочисленного типа можно увидеть по адресу Основные понятия / Основные типы .

Типы bool, char, char16_t, char32_t, wchar_t, а целочисленные типы со знаком и без знака вместе называются целыми типами. Синоним для целочисленного типа: целочисленный тип .


A double также можно преобразовать в char из-за Стандартных преобразований / преобразований с плавающей запятой .

Значение типа с плавающей запятой может быть преобразовано в значение типа целого числа. Преобразование усекается; то есть дробная часть отбрасывается.

4 голосов
/ 28 марта 2019

Так работает 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 с.

0 голосов
/ 28 марта 2019

Поскольку значения неявно преобразуются. Это также называется автоматическим преобразованием типов. Символы являются целочисленным типом, поэтому они имеют многопоточность, как и любой другой тип int - назначение значения типа double или числа с плавающей точкой усекает значение.

Это довольно часто, практически все языки программирования, которые я могу придумать, делают это.

...