Читать «Справочное руководство по C++» онлайн - страница 76
Бьярн Страустрап
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]);
R.13.1 Сопоставление описаний
Два описания функций с одинаковыми именами относятся к одной и той же функции, если они находятся в одной области видимости и имеют идентичные типы параметров (§R.13). Функция-член производного класса относится к иной области видимости, чем функция-член базового класса с тем же именем. Рассмотрим пример:
class B {
public:
int f(int);
};
class D: public B {
public:
int f(char*);
};
Здесь D::f(char*) скорее скрывает B::f(int), чем перегружает эту функцию.
void h(D* pd)
{
pd-›f(1); // ошибка: D::f(char*) скрывает B::f(int)
pd-›B::f(1); // нормально
pd-›f("Ben"); // нормально, вызов D::f
}
Функция, описанная локально, находится в иной области видимости, чем функция с файловой областью видимости.
int f(char*);
void g()
{
extern f(int);
f("asdf"); // ошибка: f(int) скрывает f(char*) поэтому
// в текущей области видимости нет f(char*)
}
Для разных вариантов перегруженной функции-члена можно задать разные правила доступа, например:
class buffer {
private:
char* p;
int size;
protected:
buffer(int s, char* store) { size = s; p = store; }
//…
public:
buffer(int s) { p = new char[size = s]; }
};
R.13.2 Сопоставление параметров
При вызове функции с данным именем происходит выбор из всех функций с этим именем, которые находятся в текущей области видимости, и для которых существуют преобразования типа, делающие вызов возможным. Выбирается та функция, которая наиболее соответствует фактическим параметрам. Она находится в области пересечения множеств функций, каждое из которых наиболее соответствуют вызову по данному фактическому параметру. Операция вызова считается допустимой, если в этом пересечении находится только один член. Функция, выбранная таким образом, должна более любой другой функции с тем же именем соответствовать вызову, хотя бы по одному из параметров (необязательно это будет один и тот же параметр для разных функций). В противном случае, вызов считается недопустимым.