compute(char) : operator char()-стандартное преобразование
Поскольку в них применяются разные конвертеры, то невозможно определить, у какой функции формальные параметры лучше соответствуют вызову. Для выбора лучшей из двух ранг последовательности стандартных преобразований не используется. Вызов помечается компилятором как неоднозначный.
Упражнение 15.12
В классах стандартной библиотеки C++ нет определений конвертеров, а большинство конструкторов, принимающих один параметр, объявлены явными. Однако определено множество перегруженных операторов. Как вы думаете, почему при проектировании было принято такое решение?
Упражнение 15.13
Почему перегруженный оператор ввода для класса SmallInt, определенный в начале этого раздела, реализован не так:
istream& operator&&( istream &is, SmallInt &si )
{
return ( is is.value );
}
Упражнение 15.14
Приведите возможные последовательности определенных пользователем преобразований для следующих инициализаций. Каким будет результат каждой инициализации?
class LongDouble {
operator double();
operator float();
};
extern LongDouble ldObj;
(a) int ex1 = ldObj;
(b) float ex2 = ldObj;
Упражнение 15.15
Назовите три множества функций-кандидатов, рассматриваемых при разрешении перегрузки функции в случае, когда хотя бы один ее аргумент имеет тип класса.
Упражнение 15.16
Какая из функций calc() выбирается в качестве наилучшей из устоявших в данном случае? Покажите последовательности преобразований, необходимых для вызова каждой функции, и объясните, почему одна из них лучше другой.
class LongDouble {
public:
LongDouble( double );
// ...
};
extern void calc( int );
extern void calc( LongDouble );
double dval;
int main() {
calc( dval ); // какая функция?
}
15.11. Разрешение перегрузки и функции-члены A
* Функции-члены также могут быть перегружены, и в этом случае тоже применяется процедура разрешения перегрузки для выбора наилучшей из устоявших. Такое разрешение очень похоже на аналогичную процедуру для обычных функций и состоит из тех же трех шагов: Отбор функций-кандидатов.
* Отбор устоявших функций.
* Выбор наилучшей из устоявших функции.
Однако есть небольшие различия в алгоритмах формирования множества кандидатов и отбора устоявших функций-членов. Эти различия мы и рассмотрим в настоящем разделе.
15.11.1. Объявления перегруженных функций-членов
Функции-члены класса можно перегружать:
class myClass {
public:
void f( double );
char f( char, char ); // перегружает myClass::f( double )
// ...
};
Как и в случае функций, объявленных в пространстве имен, функции-члены могут иметь одинаковые имена при условии, что списки их параметров различны либо по числу параметров, либо по их типам. Если же объявления двух функций-членов отличаются только типом возвращаемого значения, то второе объявление считается ошибкой компиляции:
class myClass {
public:
void mf();
double mf(); // ошибка: так перегружать нельзя
// ...
};
В отличие от функций в пространствах имен, функции-члены должны быть объявлены только один раз. Если даже тип возвращаемого значения и списки параметров двух функций-членов совпадают, то второе объявление компилятор трактует как неверное повторное объявление:
class myClass {
public:
void mf();
void mf(); // ошибка: повторное объявление
// ...
};
Все функции из множества перегруженных должны быть объявлены в одной и той же области видимости. Поэтому функции-члены никогда не перегружают функций, объявленных в пространстве имен. Кроме того, поскольку у каждого класса своя область видимости, функции, являющиеся членами разных классов, не перегружают друг друга.
Множество перегруженных функций-членов может содержать как статические, так и нестатические функции:
class myClass {
public:
void mcf( double );
static void mcf( int* ); // перегружает myClass::mcf( double )
// ...
};
Какая из функций-членов будет вызвана – статическая или нестатическая – зависит от результатов разрешения перегрузки. Процесс разрешения в ситуации, когда устояли как статические, так и нестатические члены, мы подробно рассмотрим в следующем разделе.
15.11.2. Функции-кандидаты
Рассмотрим два вида вызовов функции-члена:
mc.mf( arg );
pmc-mf( arg );