R Справочное руководство по С++

R.13 Перегрузка.

   


Назад  |  Вперёд

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

           double abs(double);
           int abs(int);

           abs(1);   // вызов abs(int)
           abs(1.0); // вызов abs(double)

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

           int f(int i)
           {
             // ...
           }

           int f(int& r)  // ошибка: типы функций
           {              // недостаточно различны
             // ...
           }

Аналогично, поскольку для любом типе T для самого T, const T и volatile T допустимо одно и то же множество инициализирующих значений, функции, типы параметров которых отличаются только указанной спецификацией, не могут иметь одинаковые имена. Однако, различить const T&, volatile T& и просто T& можно, поэтому допустимы определения функций с одним именем, которые различаются только в указанном отношении. Аналогично, допустимы определения функций с одним именем, типы параметров которых различаются только как типы вида const T*, volatile T* и просто T*. Не могут иметь одинаковые имена функции, которые отличаются только типом возвращаемого значения. Не могут иметь одинаковые имена функции-члены, одна из которых статическая, а другая нет ($$R.9.4). С помощью конструкции typedef не создаются новые типы, а только определяется синоним типа ($$R.7.1.3), поэтому функции, которые отличаются только за счет использования типов, определенных с помощью typedef, не могут иметь одинаковые имена. Приведем пример:

           typedef int Int;

           void f(int i) { /* ... */ }
           void f(Int i) { /* ... */ } // ошибка: переопределение f

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

           enum E { a };

           void f(int i) { /* ... */ }
           void f(E i)   { /* ... */ }

Типы параметров, которые различаются только тем, что в одном используется указатель *, а в другом массив [], считаются идентичными. Напомним, что для типа параметра важны только второй и последующие индексы многомерного массива ($$R.8.2.4). Подтвердим сказанное примером:

           f(char*);
           f(char[]);       // идентично f(char*);
           f(char[7]);      // идентично f(char*);
           f(char[9]);      // идентично f(char*);
           g(char(*)[10]);
           g(char[5][10]);  // идентично g(char(*)[10]);
           g(char[7][10]);  // идентично g(char(*)[10]);
           g(char(*)[20]);  // отлично от g(char(*)[10]);

Назад  |  Вперёд


OtDiatlovaOU
К началу книги

Оформление и дизайн книги OtDiatlovaOU.
Вся книга, архив.