
Int main()
{
// Неоднозначности нет, вызывается функция myfunc(double).
cout << myfunc (10.1) << " ";
// Неоднозначность.
cout << myfunc(10);
return 0;
}
float myfunc(float i)
{
return i;
}
double myfunc(double i)
{
return -i;
}
Здесь благодаря перегрузке функция myfunc() может принимать аргументы либо типа float, либо типа double. При выполнении строки кода
cout << myfunc (10.1) << " ";
не возникает никакой неоднозначности: компилятор "уверенно" обеспечивает вызов функции myfunc(double), поскольку, если не задано явным образом иное, все литералы с плавающей точкой в C++ автоматически получают тип double. Но при вызове функции myfunc() с аргументом, равным целому числу 10, в программу вносится неоднозначность, поскольку компилятору неизвестно, в какой тип ему следует преобразовать этот аргумент: float или double. Оба преобразования допустимы. В такой неоднозначной ситуации будет выдано сообщение об ошибке, и программа не скомпилируется.
На примере предыдущей программы хотелось бы подчеркнуть, что неоднозначность в ней вызвана не перегрузкой функции myfunc(), объявленной дважды для приема double- и float-аргумента, а использованием при конкретном вызове функции myfunc() аргумента неопределенного для преобразования типа. Другими словами, ошибка состоит не в перегрузке функции myfunc(), а в конкретном ее вызове.
А вот еще один пример неоднозначности, вызванной автоматическим преобразованием типов в C++.
// Еще одна ошибка, вызванная неоднозначностью.
#include <iostream>
using namespace std;
char myfunc(unsigned char ch);
char myfunc(char ch);
Int main()
{
cout << myfunc('c'); // Здесь вызывается myfunc(char).
cout << myfunc(88) << " "; // Вносится неоднозначность.
return 0;
}
char myfunc(unsigned char ch)
{
return ch-1;
}
char myfunc(char ch)
{
return ch+1;
}
В C++ типы unsigned char и char не являются существенно неоднозначными. (Это — различные типы.) Но при вызове функции myfunc() с целочисленным аргументом 88 компилятор "не знает", какую функцию ему выполнить, т.е. в значение какого типа ему следует преобразовать число 88: типа char или типа unsigned char? Оба преобразования здесь вполне допустимы.
Неоднозначность может быть также вызвана использованием в перегруженных функциях аргументов, передаваемых по умолчанию. Для примера рассмотрим следующую программу.
// Еще один пример неоднозначности.
#include <iostream>
using namespace std;
int myfunc(int i);
int myfunc(int i, int j=1);
Int main()
{
cout << myfunc(4, 5) << " "; // неоднозначности нет
cout << myfunc(10); // неоднозначность
return 0;
}
int myfunc(int i)
{
return i;
}
int myfunc(int i, int j)
{
return i*j;
}
Здесь в первом обращении к функции myfunc() задается два аргумента, поэтому у компилятора нет никаких сомнений в выборе нужной функции, а именно myfunc(int i, int j), т.е. никакой неоднозначности в этом случае не привносится. Но при втором обращении к функции myfunc() мы получаем неоднозначность, поскольку компилятор "не знает", то ли ему вызвать версию функции myfunc(), которая принимает один аргумент, то ли использовать возможность передачи аргумента по умолчанию к версии, которая принимает два аргумента.
Программируя на языке C++, вам еще не раз придется столкнуться с ошибками неоднозначности, которые, к сожалению, очень легко "проникают" в программы, и только опыт и практика помогут вам избавиться от них.