Аргументы со значениями по умолчанию
Наличие аргументов со значениями по умолчанию способно расширить множество устоявших функций. Устоявшими являются функции, которые вызываются с данным списком фактических аргументов. Но такая функция может иметь больше формальных параметров, чем задано фактических аргументов, в том случае, когда для каждого неуказанного параметра есть некое значение по умолчанию:
extern void ff( int );
extern void ff( long, int = 0 );
int main() {
ff( 2L ); // соответствует ff( long, 0 );
ff( 0, 0 ); // соответствует ff( long, int );
ff( 0 ); // соответствует ff( int );
ff( 3.14 ); // ошибка: неоднозначность
}
Для первого и третьего вызовов функция ff() является устоявшей, хотя передан всего один фактический аргумент. Это обусловлено следующими причинами:
1. для второго формального параметра есть значение по умолчанию;
2. первый параметр типа long точно соответствует фактическому аргументу в первом вызове и может быть приведен к типу аргумента в третьем вызове за счет последовательности, имеющей ранг стандартного преобразования.
Последний вызов является неоднозначным, поскольку обе устоявших функции могут быть выбраны, если применить стандартное преобразование к первому аргументу. Функции ff(int) не отдается предпочтение только потому, что у нее один параметр.
Упражнение 9.9
Объясните, что происходит при разрешении перегрузки для вызова функции compute() внутри main(). Какие функции являются кандидатами? Какие из них устоят после первого шага? Какие последовательности преобразований надо применить к фактическому аргументу, чтобы он соответствовал формальному параметру для каждой устоявшей функции? Какая функция будет наилучшей из устоявших?
namespace primerLib {
void compute();
void compute( const void * );
}
using primerLib::compute;
void compute( int );
void compute( double, double = 3.4 );
void compute( char*, char* = 0 );
int main() {
compute( 0 );
return 0;
}
Что будет, если using-объявление поместить внутрь main() перед вызовом compute()? Ответьте на те же вопросы.