С++ для начинающих




Наилучшая из устоявших функция - часть 3


2b.  Стандартное преобразование между целым и плавающим типом приводит аргументы от типа char к типу double.

Ранг первой последовательности – расширение типа (самое худшее из примененных изменений), тогда как ранг второй – стандартное преобразование. Так как расширение типа лучше, чем преобразование, то в качестве наилучшей из устоявших для данного вызова выбирается функция libs_R_us::max(int,int).

Если ранжирование последовательностей преобразований аргументов не может выявить единственной устоявшей функции, то вызов считается неоднозначным. В данном примере для обоих вызовов calc() требуется такая последовательность:

1.      Преобразование l-значения в r-значение для извлечения значений аргументов i и j.

2.      Стандартное преобразование для приведения типов фактических аргументов к типам соответствующих формальных параметров.

Поскольку нельзя сказать, какая из этих последовательностей лучше другой, вызов неоднозначен:

int i, j;

extern long calc( long, long );

extern double calc( double, double );

void jj() {

   // ошибка: неоднозначность, нет наилучшего соответствия

   calc( i, j );

}

Преобразование спецификаторов (добавление спецификатора const или volatile к типу, который адресует указатель) имеет ранг точного соответствия. Однако, если две последовательности трансформаций отличаются только тем, что в конце одной из них есть дополнительное преобразование спецификаторов, то последовательность без него считается лучше. Например:

void reset( int * );

void reset( const int * );

int* pi;

int main() {

   reset( pi );   // без преобразования спецификаторов лучше:

                  // выбирается reset( int * )

   return 0;

}

Последовательность стандартных преобразований, примененная к фактическому аргументу для первой функции-кандидата reset(int*), – это точное соответствие, требуется лишь переход от l-значения к r-значению, чтобы извлечь значение аргумента. Для второй функции-кандидата reset(const int *) также применяется трансформация l-значения в r-значение, но за ней следует еще и преобразование спецификаторов для приведения результирующего значения от типа “указатель на int” к типу “указатель на const int”. Обе последовательности представляют собой точное соответствие, но неоднозначности при этом не возникает. Так как вторая последовательность отличается от первой наличием трансформации спецификаторов в конце, то последовательность без такого преобразования считается лучшей. Поэтому наилучшей из устоявших функций будет reset(int*).




Содержание  Назад  Вперед