Правила перегрузки функций

Посмотрите на этот код (например):

#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 ); или вы можете явно привести тип к одному из предоставленных типов параметров перегрузки.

Другие вопросы по тегам