Основной причиной неоднозначности в C++ является автоматическое преобразование типов. В C++ делается попытка автоматически преобразовать тип аргументов, используемых для вызова функции, в тип параметров, определенных функцией. Рассмотрим пример.

int myfunc(double d);

.

.

.

cout << myfunc('c'); // Ошибки нет, выполняется преобразование типов.

Как отмечено в комментарии, ошибки здесь нет, поскольку C++ автоматически преобразует символ 'c' в его double-эквивалент. Вообще говоря, в C++ запрещено довольно мало видов преобразований типов. Несмотря на то что автоматическое преобразование типов — это очень удобно, оно, тем не менее, является главной причиной неоднозначности. Рассмотрим следующую программу.

// Неоднозначность вследствие перегрузки функций.

#include

using namespace std;

float myfunc(float i);

double myfunc(double i);

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

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

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;

}

Перейти на страницу:

Все книги серии Изучайте C++ с профессионалами

Похожие книги