Перегрузка функций становится неоднозначной

При перегрузке функций:

void add(int a)
{
    a=7;
    cout<<"int";
}
void add(double a)
{
    a=8.4;
    cout<<"double";
}
void add(int *b)
{
    *b=4;
    cout<<"pointer";
}
int main()
{
    char i='a';   //char
    add(i);
    return 0;
}

ВЫХОД: int

Это работало нормально, несмотря на отсутствие функции с типом данных char в качестве параметра.

Но при компиляции кода ниже:

void add(char a)
{
    a='a';
    cout<<"int";
}
void add(double a)
{
    a=8.4;
    cout<<"double";
}
void add(int *b)
{
    *b=4;
    cout<<"pointer";
}
int main()
{
    int i=4;  //int
    add(i);
    return 0;
}

Выдал ошибку (компилятор gcc):

cpp | 21 | ошибка: вызов перегруженного add (int &) неоднозначен

Какая логика за этим? А как отследить контроль прохождения или выдачи таких кодов?


person wrangler    schedule 03.11.2015    source источник
comment
en.cppreference.com/w/cpp/language/overload_resolution   -  person Karoly Horvath    schedule 03.11.2015
comment
Что вы ожидали?   -  person n. 1.8e9-where's-my-share m.    schedule 03.11.2015
comment
@ n.m. Я ожидал такой же ошибки для кода выше ....   -  person wrangler    schedule 03.11.2015


Ответы (3)


Этот пример сводится к разнице между целочисленным продвижением и целочисленным преобразованием. Короче говоря, продвижение по службе:

Prvalue целочисленного типа, отличного от bool, char16_t, char32_t или wchar_t, чей ранг целочисленного преобразования (4.13) меньше, чем ранг int, может быть преобразовано в prvalue типа int, если int может представлять все значения исходного типа ; в противном случае исходное prvalue может быть преобразовано в prvalue типа unsigned int. [...] Эти преобразования называются интегральными акциями.

тогда как целочисленное преобразование является более общим:

Prvalue целочисленного типа может быть преобразовано в prvalue другого целочисленного типа. [...] Преобразования, разрешенные как целые продвижения, исключаются из набора целых преобразований.

Целостное продвижение - это лучшее преобразование, чем интегральное преобразование с точки зрения разрешения перегрузки.


В первом примере у нас есть:

add(int );    // (1)
add(double ); // (2)
add(int* );   // (3)

и звонят с char. Только первые два жизнеспособны, оба предполагают преобразование. (1) включает целочисленное продвижение, которое имеет ранговое продвижение. (2) включает преобразование с плавающей точкой в ​​интеграл, которое имеет преобразование рангов. Поощрение имеет более высокий рейтинг, чем Конверсия, поэтому (1) однозначно предпочтительнее. введите описание изображения здесь

Теперь во втором примере у нас есть:

add(char );   // (1)
add(double ); // (2)
add(int* );   // (3)

и звонят с int. Опять же, жизнеспособны только первые два, и оба предполагают преобразование. (1) на этот раз включает интегральное преобразование (поскольку char имеет более низкий ранг, чем int) и (2) по-прежнему включает преобразование с плавающей запятой, оба из которых имеют одинаковый ранг: преобразование. Поскольку у нас есть две конверсии одного ранга, не существует «лучшей» конверсии, поэтому нет лучшего жизнеспособного кандидата. Таким образом, мы имеем неоднозначное разрешение.

person Barry    schedule 03.11.2015
comment
Спасибо за ваш ответ, вы также можете предоставить ссылки на свой ответ. - person wrangler; 13.08.2017

Причина в том, что когда нет точного соответствия типа, компилятор ищет самое близкое совпадение. Вот почему, когда это было - char i='a'; ближайшим совпадением было void add(int a)

но когда он int i=4; //int, есть 2 совпадения. так вот почему это неоднозначно.

person Amit K. Saha    schedule 03.11.2015
comment
add (int * b) и add (char a) оба получают переменную типа int - person Amit K. Saha; 03.11.2015
comment
Я так не думаю, поскольку удаление функции с параметром double для приведенного ниже кода выполнено успешно. - person wrangler; 03.11.2015
comment
Извините моя ошибка. это будет add (int * b) и add (double a), кто соревнуется. - person Amit K. Saha; 03.11.2015

char вписывается в int без переполнения и потери точности, что объясняет первый код.

Но int не вписывается в char (переполнение), double (отсутствие точности) или int* (несовместимый тип).

person emlai    schedule 03.11.2015
comment
Это «неоднозначно», так что разве это не слишком подходящий сценарий вместо недостаточного? - person Amit K. Saha; 03.11.2015
comment
@zenith, когда я удалил функцию параметра char, он дал результат double для кода ниже ..... так что int вписывается в double. - person wrangler; 03.11.2015
comment
@zenith и то же самое для char, когда я удалил double, он дал результат int (под параметром char), поэтому int также вписывается в char i think - person wrangler; 03.11.2015