Странный неоднозначный вызов перегруженной функции
Я пытаюсь
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)
?
Ответы
Ответ 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. Продвижение происходит только тогда, когда совпадение не найдено.
См: -
Компьютерные науки с С++
Сумита Арора
Глава: Перегрузка функций