Правила перегрузки функций
Посмотрите на этот код (например):
#include <iostream>
void print(unsigned int value);
void print(float value);
int main() {
print('a');
print(0);
print(3.14159);
return 0;
}
Я получаю следующую ошибку:
'print (char)' неоднозначно
В чем здесь проблема? Я понял, что более чем одна функция подходит для любого вызова из основного (для печати функции). Но какие на самом деле правила в function overloading
(Как я могу узнать, что подходит для чего, между какими типами существует приведение типов и т. Д.)
Как я могу узнать, что более одной функции соответствуют вызову? (еще пример: это не очевидно, как понять, что две функции соответствуют вызову)
#include <iostream>
void print(unsigned int value);
void print(int value);
int main() {
print(2.5);
}
2 ответа
Ошибки, которые вы получаете из-за отсутствия версии print
:
print('a'); // calling print(int)
print(0); // calling print(int)
print(3.14159); // calling print(double) not float
Как вы видете print(int)
а также print(double)
также отсутствуют print(char)
отсутствует, вы получаете эти ошибки. когда print(char)
например, не предусмотрено, то поиск компилятором для print(int)
таким образом, он преобразует переданное значение в целое число.
Чтобы решить эту проблему, вы должны добавить версию перегруженного print
или приведите явно значение, переданное в:
1- Перегрузка печати:
void print(int value){ cout << "int: " << value << endl;}
void print(unsigned int value){ cout << "ui: " << value << endl;}
void print(float value){cout << "float: " << value << endl;}
void print(char c){ cout << "Char: " << c << endl;}
void print(double value){cout << "double: " << value << endl;}
2- Кастинг:
print((unsigned int)'a'); // or (float)
print((unsigned int)0); // or (float)
print(3.14159f); // or (float)3.14159 or (unsigned int)3.14159
- Имейте в виду, что
print(3.14159);
это вызовprint(double);
не дляfloat
сделать это для поплавка:print(3.14159f);
Когда вы работаете с перегрузкой функций, компилятор выполняет большую часть работы за кулисами, чтобы выполнить разрешение перегрузки функций. Подробные сведения следует перечислить здесь, однако я могу предоставить некоторые ссылки, которые могут оказаться полезными, и попытаться описать некоторые из наиболее важных частей.
Есть 3 возможных результата:
- Совпадение найдено. Вызов разрешен с определенной перегрузкой
- Совпадение не найдено. Аргументы не могут быть сопоставлены с любой перегрузкой
- Неоднозначное совпадение найдено. Аргументы совпали с более чем одной перегрузкой
Основной порядок действий компилятора:
- Найти точное соответствие на основе списка параметров
- Пытается найти соответствие через продвижение
- Пытается найти совпадение с помощью стандартного преобразования
- Пытается найти совпадение с помощью пользовательского преобразования
Так как же это определить, если вызов неоднозначен?
Поскольку каждая перегрузка должна иметь уникальные параметры и в связи с тем, что все стандартные преобразования и все пользовательские преобразования считаются равными; если вызов функции соответствует более чем одному действительному кандидату определения объявления посредством стандартного или пользовательского преобразования, то результат будет неоднозначным.
Из вашего примера:
void print( unsigned int value );
void print( float value );
print( 'a' );
print( 0 );
print( 3.14159 );
В случае print( 'a' );
C++ не может найти точное совпадение. Сначала попробую продвинуть 'a'
для int
, но нет print(int)
функция, которая объявлена-определена. Затем он попытается использовать стандартное преобразование, он может преобразовать 'a'
как unsigned int
и floating point
значение. И поскольку все стандартные преобразования считаются равными, это приводит к неоднозначности.
Чтобы устранить эту двусмысленность, вы можете просто declare-define
необходимые версии print( type );
или вы можете явно привести тип к одному из предоставленных типов параметров перегрузки.