Подтвердить что ты не робот

Странный неоднозначный вызов перегруженной функции

Я пытаюсь

void function(int y,int w)
{
    printf("int function");

}


void function(float y,float w)
{
    printf("float function");
}


int main()
{
    function(1.2,2.2);
    return 0;
}

Я получаю ошибку, например..

error C2668: 'function' : ambiguous call to overloaded function

и когда я пытаюсь вызвать function(1.2,2) или function(1,2.2), он печатает как " функция int"

Пожалуйста, уточните, когда вызывается function(float y,float w)?

4b9b3361

Ответ 1

Посмотрите сообщение об ошибке из gcc:

a.cpp:16: error: call of overloaded ‘function(double, double)’ is ambiguous
a.cpp:3: note: candidates are: void function(int, int)
a.cpp:9: note:                 void function(float, float)

Вызов любой из функций потребует усечения, поэтому ни один из них не является предпочтительным по сравнению с другим. Я подозреваю, что вы действительно хотите void function(double y,double w). Помните, что в C/С++ тип с плавающей запятой по умолчанию для литералов и передачи параметров - double, NOT float.

UPDATE

Если вы действительно не хотите менять подпись функции с float на double, вы всегда можете использовать литералы, которые напечатаны как float. Если вы добавите суффикс f к номерам с плавающей запятой, они будут напечатаны с плавающей запятой.

Вашими примерами будут function(1.2f, 2f) и function(1, 2.2f).

Ответ 2

Что такое перегрузка оператора?

Знаменитая Sbi's > перегрузка faq отвечает на это очень подробно.

Почему две версии function в OP допускаются к существованию?

Обратите внимание, что они принимают разные типы параметров функций (int и float) и, следовательно, квалифицируются как допустимые перегрузки функций.

Что такое разрешение перегрузки?

Это процесс выбора наиболее подходящей функции/оператора с помощью реализации компилятора. Если существует наилучшая жизнеспособная функция и она уникальна, разрешение перегрузки преуспевает и приводит к ее результату. В противном случае разрешение перегрузки завершается с ошибкой, и вызов обрабатывается как плохо сформированный, а компилятор предоставляет диагностику. Компилятор использует неявная последовательность преобразований, чтобы найти наилучшую функцию соответствия.

С++ 03 Стандарт 13.3.3.1 Неявные преобразования:

Неявная последовательность преобразования представляет собой последовательность преобразований, используемых для преобразования аргумента в вызов функции к типу соответствующего параметра вызываемой функции.

Неявные последовательности преобразования могут быть одной из следующих категорий:

  • Стандартная последовательность преобразования (13.3.3.1.1)
  • Пользовательская последовательность преобразований (13.3.3.1.2)
  • Последовательность преобразования многоточия (13.3.3.1.3)

Обратите внимание, что каждый из них оценивается для определения наилучшей жизнеспособной функции. Лучшая жизнеспособная функция - это та, у которой параметры имеют либо более совершенные, либо равноценные неявные последовательности преобразований, чем все другие жизнеспособные функции. Стандартная информация подробно описана в каждом из этих разделов. Стандартная последовательность преобразования имеет отношение к этому случаю, она суммируется как:

enter image description here

С достаточным фоном для перегрузки разрешения.
рассмотрим примеры кода в OP:

function(1.2,2.2);

Важное правило: 1.2 и 2.2 являются литералами, и они рассматриваются как тип данных double.

Во время отображения неявных преобразований:
Оба литерала параметров функции с типом double нуждаются в ранге преобразования, чтобы либо вызвать версию float, либо int, и ни одна из них не лучше, чем другая, они точно совпадают с рангом конверсии. Компилятор не может определить наилучшее жизнеспособное соответствие, и он сообщает о двусмысленности.

function(1.2,2);

При отображении последовательности неявных преобразований:
Один из параметров функции 2 имеет точное соответствие с версией функции int, а другой 1.2 имеет ранг преобразования. Для функции, которая принимает float в качестве параметров, неявные последовательности преобразования для обоих параметров имеют ранг преобразования.
Таким образом, функция, которая принимает версию int, лучше, чем версия float, и является наилучшим совпадением и получает вызов.

Как разрешить перегрузку ошибок неоднозначности?

Если вы не хотите, чтобы неявное преобразование последовательности преобразований выбрасывало вас, просто предоставляйте функции и вызывайте их таким образом, чтобы параметры были точно совпадают. Поскольку точное совпадение очков над всеми остальными, у вас есть определенная гарантия того, что ваша желаемая функция будет вызвана. В вашем случае есть два способа сделать это:

Решение 1:

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

function(1.2f,2.2f);

Так как 1.2f и 2.2f рассматриваются как типы float, они точно соответствуют версии функции float.

Решение 2:

Предоставить функцию перегрузки, которая точно соответствует типу параметра в вызываемой функции.

function(double, double){}

Так как 1.2 и 2.2 рассматриваются как double, вызываемая функция точно соответствует этой перегрузке.

Ответ 3

Если вы не хотите (как объяснено в принятом ответе):

  • использовать плавающие литералы, например. 1.2f
  • или измените существующую перегрузку float на double

Вы можете добавить еще одну перегрузку, которая вызывает float:

void function(double y, double w)
{
    function((float)y, (float)w);
}

Теперь ваш код в main вызовет указанную выше функцию, которая вызовет перегрузку float.

Ответ 4

Перегрузка функций в приведенном выше примере имеет неоднозначные вызовы, потому что тип возврата одинаковый, а второй аргумент в вызове функции - двойной, который можно рассматривать как int или float, и, следовательно, компилятор смущает, какую функцию выполнить.

Ответ 5

Я надеюсь, что эта помощь Этот код является самоискусным для всех комбинаций

Вам нужно отправить два float для вызова функции float

#include<iostream>
#include<stdio.h>

using namespace std;

//when arguments are both int
void function(int y,int w) {
    printf("int function\n");
}

//when arguments are both double
void function(double y, double w) {
    printf("double function\n");
}

//when arguments are both float
void function(float y, float w) {
    printf("float function\n");
}

//when arguments are int and float
void function(int y, float x) {
    printf("int float function\n");
}

//when arguments are float and int
void function(float y,int w) {
    printf("float int function\n");
}

//when arguments are int and double
void function(int y, double w) {
    printf("int double function\n");
}

//when arguments are double and int
void function(double y, int x) {
    printf("double int function\n");
}

//when arguments are double and float
void function(double y, float x) {
    printf("double float function\n");
}

//when arguments are float and double
void function(float y, double x) {
    printf("float double function\n");
}



int main(int argc, char *argv[]) {
    function(1.2,2.2);
    function(1.2f,2.2f);
    function(1,2);
    function(1.2,2.2f);
    function(1.2f,2.2);
    function(1,2.2);
    function(1,2.2f);
    function(1.2,2);
    function(1.2f,2);
    return 0;
}

Ответ 6

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

int main()
{
    function(1.3f,                    2.4f);
    function(1.3f,                    static_cast<float>(2.4));
    function(static_cast<float>(1.3), static_cast<float>(2.4));
    function(static_cast<float>(1),   static_cast<float>(2));
    return 0;
}

Ответ 7

По умолчанию десятичный считается двойным. Если вы хотите, чтобы десятичные числа были поплавками, вы их суффикс с f. В вашем примере, когда вы вызываете функцию (1.2.2.2), компилятор рассматривает значения, которые вы передали им как двойные, и, следовательно, вы получаете несоответствие в сигнатуре функции.

function(1.2,1.2) ====> function(double,double)

Если вы хотите сохранить подпись функции, вам нужно использовать суффикс с плавающей запятой, передавая литерал с плавающей запятой.

function(1.2f,1.2f) ====>   function(float,float).

Если вас больше интересует знание литералов с плавающей точкой, вы можете сослаться на

Почему значение плавающей запятой, такое как 3.14, считается по умолчанию в MSVC по умолчанию?

Ответ 8

Как и другие, вы даете удваиваете свою перегруженную функцию, предназначенную для плавающих. У самой перегрузки нет ошибок.

Здесь правильное использование перегруженной функции (обратите внимание на "f" справа после чисел):

function(1.0f, 2.0f);

Ответ 9

function(1.2,2.2);

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

double p1 = 1.2;
double p2 = 2.2;
void (*fn)(double /*decltype(p1)*/, double /*decltype(p2)*/) = function;

Теперь компилятор ищет "функцию", которая принимает два удвоения. Точного совпадения нет. Итак, он ищет функцию, которая принимает аргумент, который может быть отличен из двух пар. Есть два совпадения.

function(int, int);
function(float, float);

У вас есть несколько вариантов.

  • Добавьте точную перегрузку соответствия.

    функция void (двойная, двойная) {   printf ( "двойная функция \n" ); }

  • Использовать кастинг.

    function (static_cast (1.2), static_cast (2.2));

  • Вызов функции с поплавками вместо двухлокальных:

    (1.2f, 2.2f);

Ответ 10

Попробуйте это

#include <iostream>
using namespace std;

void print(int i){
    cout << i << endl;
}

void print(float i){
    cout << i << endl;
}

int main(){
    print(5);
    print(5.5f);
    return 0;
}

При перегрузке функции, когда float может конфликтовать с другим типом данных в других функциях с тем же именем, возможно, это способ преодолеть это. Я попробовал, чтобы это сработало.

Ответ 11

Представьте, как будут переданы ваши аргументы.

Если он передается как 1,2 и 2.2 в функцию (int, int), тогда он будет усечен до 1 и 2.

Если он передается как 1.2 и 2.2 в (float, float), он будет обрабатываться как есть.

Итак, вот где заблуждается двусмысленность.

Я нашел два способа решить эту проблему. Во-первых, это использование литералов: -

int main()
{
        function(1.2F,2.2F);
    return 0;
}

Во-вторых, и как мне это нравится, он всегда работает (и также может использоваться для преобразования и продвижения по умолчанию в С++). Для int: -

int main()
{
int a=1.2, b=2.2;
    function(a,b);
    return 0;
}

Для Float: -

int main()
{
float a=1.2, b=2.2;
    function(a,b);
    return 0;
}

Итак, вместо использования реальных ЦИФРОВ. Лучше сначала объявить их как тип, а затем перегрузить!

Посмотрите сейчас, если вы отправите его как (1.2,2) or (1,2.2), тогда компилятор может просто отправить его в функцию int, и это сработает. Однако, чтобы отправить его в функцию float, компилятору пришлось бы продвигать 2 к float. Продвижение происходит только тогда, когда совпадение не найдено.

См: - Компьютерные науки с С++ Сумита Арора Глава: Перегрузка функций