Using-директивы также оказывают влияние на состав множества функций-кандидатов. Предположим, мы решили их использовать, чтобы сделать функции max() из пространства имен libs_R_us видимыми в func(). Если разместить следующую using-директиву в глобальной области видимости, то множество функций-кандидатов будет состоять из глобальной функции max(char, char) и функций max(int, int) и max(double, double), объявленных в libs_R_us:

namespace libs_R_us {

int max( int, int );

double max( double, double );

}

char max( char, char );

using namespace libs_R_us; // using-директива

void func()

{

max( 87, 65 ); // вызывается libs_R_us::max( int, int )

max( 35.5, 76.6 ); // вызывается libs_R_us::max( double, double )

max( 'J', 'L' ); // вызывается ::max( int, int )

}

Что будет, если поместить using-директиву в локальную область видимости, как в следующем примере?

void func()

{

// using-директива

using namespace libs_R_us;

// те же вызовы функций, что и выше

}

Какие из функций max() окажутся среди кандидатов? Напомним, что using-директива делает члены пространства имен видимыми, словно они были объявлены вне этого пространства, в той точке, где такая директива помещается. В нашем примере члены libs_R_us видимы в локальной области функции func(), как будто они объявлены вне пространства – в глобальной области. Отсюда следует, что множество перегруженных функций, видимых внутри func(), то же, что и раньше, т.е. включает в себя

max( char, char );

libs_R_us::max( int, int );

libs_R_us::max( double, double );

В локальной или глобальной области видимости появляется using-директива, на разрешение вызовов функции func() не влияет:

void func()

{

using namespace libs_R_us;

max( 87, 65 ); // вызывается libs_R_us::max( int, int )

max( 35.5, 76.6 ); // вызывается libs_R_us::max( double, double )

max( 'J', 'L' ); // вызывается ::max( int, int )

}

Итак, множество кандидатов состоит из функций, видимых в точке вызова, включая и те, которые введены using-объявлениями и using-директивами, а также из функций, объявленных в пространствах имен, ассоциированных с типами фактических аргументов. Например:

namespace basicLib {

int print( int );

double print( double );

}

namespace matrixLib {

class matrix { /* ... */ };

void print( const maxtrix );

}

void display()

{

using basicLib::print;

matrixLib::matrix mObj;

print( mObj ); // вызывается maxtrixLib::print( const maxtrix )

print( 87 ); // вызывается basicLib::print( const maxtrix )

}

Кандидатами для print(mObj) являются введенные using-объявлением внутри display() функции basicLib::print(int) и basicLib::print(double), поскольку они видимы в точке вызова. Так как фактический аргумент функции имеет тип matrixLib::matrix, то функция print(), объявленная в пространстве имен matrixLib, также будет кандидатом. Каковы функции-кандидаты для print(87)? Только basicLib::print(int) и basicLib::print(double), видимые в точке вызова. Поскольку аргумент имеет тип int, дополнительное пространство имен в поисках других кандидатов не рассматривается.

<p>9.4.2. Устоявшие функции</p>

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

В следующем примере для вызова f(5.6) есть две устоявшие функции: f(int) и f(double).

void f();

void f( int );

void f( double );

void f( char*, char* );

int main() {

f( 5.6 ); // 2 устоявшие функции: f( int ) и f( double )

return 0;

}

Перейти на страницу:

Похожие книги