Мониторинг обменных курсов валют
18c0693f

Три шага разрешения перегрузки


Разрешением перегрузки функции

называется процесс выбора той функции из множества перегруженных, которую следует вызвать. Этот процесс основывается на указанных при вызове аргументах. Рассмотрим пример:

T t1, t2;

void f( int, int );

void f( float, float );

int main() {

   f( t1, t2 );

   return 0;

}

Здесь в ходе процесса разрешения перегрузки в зависимости от типа T определяется, будет ли при обработке выражения f(t1,t2) вызвана функция f(int,int) или f(float,float) или зафиксируется ошибка.

Разрешение перегрузки функции – один и самых сложных аспектов языка C++. Пытаясь разобраться во всех деталях, начинающие программисты столкнутся с серьезными трудностями. Поэтому в данном разделе мы представим лишь краткий обзор того, как происходит разрешение перегрузки, чтобы у вас составилось хоть какое-то впечатление об этом процессе. Для тех, кто хочет узнать больше, в следующих двух разделах приводится более подробное описание.

Процесс разрешения перегрузки функции состоит из трех шагов, которые мы покажем на следующем примере:

void f();

void f( int );

void f( double, double = 3.4 );

void f( char *, char * );

void main() {

   f( 5.6 );

   return 0;

}

При разрешении перегрузки функции выполняются следующие шаги:

1.      Выделяется множество перегруженных функций для данного вызова, а также свойства списка аргументов, переданных функции.

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

3.      Находится функция, которая лучше всего соответствует вызову.

Рассмотрим последовательно каждый пункт.

На первом шаге необходимо идентифицировать множество перегруженных функций, которые будут рассматриваться при данном вызове. Вошедшие в это множество функции называются кандидатами. Функция-кандидат – это функция с тем же именем, что и вызванная, причем ее объявление видимо в точке вызова. В нашем примере есть четыре таких кандидата: f(), f(int), f(double, double) и f(char*, char*).


После этого идентифицируются свойства списка переданных аргументов, т.е. их количество и типы. В нашем примере список состоит из двух аргументов типа double.

На втором шаге среди множества кандидатов отбираются устоявшие (viable) – такие, которые могут быть вызваны с данными аргументами, Устоявшая функция либо имеет столько же формальных параметров, сколько фактических аргументов передано вызванной функции, либо больше, но тогда для каждого дополнительного параметра должно быть задано значение по умолчанию. Чтобы функция считалась устоявшей, для любого фактического аргумента, переданного при вызове, обязано существовать преобразование к типу формального параметра, указанного в объявлении.

В нашем примере есть две устоявших функции, которые могут быть вызваны с приведенными аргументами: