9.4.2. Устоявшие функции
9.4.2. Устоявшие функции
Устоявшая функция относится к числу кандидатов. В списке ее формальных параметров либо то же самое число элементов, что и в списке фактических аргументов вызванной функции, либо больше. В последнем случае для дополнительных параметров задаются значения по умолчанию, иначе функцию нельзя будет вызвать с данным числом аргументов. Чтобы функция считалась устоявшей, должно существовать преобразование каждого фактического аргумента в тип соответствующего формального параметра. (Такие преобразования были рассмотрены в разделе 9.3.)
В следующем примере для вызова f(5.6) есть две устоявшие функции: f(int) и f(double).
void f();
void f( int );
void f( double );
void f( char*, char* );
int main() {
f( 5.6 ); // 2 устоявшие функции: f( int ) и f( double )
return 0;
}
Функция f(int) устояла, так как она имеет всего один формальный параметр, что соответствует числу фактических аргументов в вызове. Кроме того, существует стандартное преобразование аргумента типа double в int. Функция f(double) также устояла; она тоже имеет один параметр типа double, и он точно соответствует фактическому аргументу. Функции-кандидаты f() и f(char*, char*) исключены из списка устоявших, так как они не могут быть вызваны с одним аргументом.
В следующем примере единственной устоявшей функцией для вызова format(3) является format(double). Хотя кандидата format(char*) можно вызывать с одним аргументом, не существует преобразования из типа фактического аргумента int в тип формального параметра char*, а следовательно, функция не может считаться устоявшей.
char* format( int );
void g() {
// глобальная функция format( int ) скрыта
char* format( double );
char* format( char* );
format(3); // есть только одна устоявшая функция: format( double )
}
В следующем примере все три функции-кандидата оказываются устоявшими для вызова max() внутри func(). Все они могут быть вызваны с двумя аргументами. Поскольку фактические аргументы имеют тип int, они точно соответствуют формальным параметрам функции libs_R_us::max(int, int) и могут быть приведены к типам параметров функции libs_R_us::max(double, double) с помощью трансформации целых в плавающие, а также к типам параметров функции libs_R_us::max(char, char) посредством преобразования целых типов.
namespace libs_R_us {
int max( int, int );
double max( double, double );
}
// using-объявление
using libs_R_us::max;
char max( char, char );
void func()
{
// все три функции max() являются устоявшими
max( 87, 65 ); // вызывается using libs_R_us::max( int, int )
}
Обратите внимание, что функция-кандидат с несколькими параметрами исключается из числа устоявших, как только выясняется, что один из фактических аргументов не может быть приведен к типу соответствующего формального параметра, пусть даже для всех остальных аргументов такое преобразование существует. В следующем примере функция min(char *, int) исключается из множества устоявших, поскольку нет возможности трансформации типа первого аргумента int в тип соответствующего параметра char *. И это происходит несмотря на то, что второй аргумент точно соответствует второму параметру.
extern double min( double, double );
extern double min( char*, int );
void func()
{
// одна функция-кандидат min( double, double )
min( 87, 65 ); // вызывается min( double, double )
}
Если после исключения из множества кандидатов всех функций с несоответствующим числом параметров и тех, для параметров которых не оказалось подходящего преобразования, не осталось устоявших, то обработка вызова функции заканчивается ошибкой компиляции. В таком случае говорят, что соответствия не найдено.
void print( unsigned int );
void print( char* );
void print( char );
int *ip;
class SmallInt { /* ... */ };
SmallInt si;
int main() {
print( ip ); // ошибка: нет устоявших функций: соответствие не найдено
print( si ); // ошибка: нет устоявших функций: соответствие не найдено
return 0;
}