extern void print( const string );
extern void print( double ); // перегружает print()
}
namespace Disney {
// отдельная область видимости:
// не перегружает функцию print() из пространства имен IBM
extern void print( int );
}
Использование using-объявлений и using-директив помогает сделать члены пространства имен доступными в других областях видимости. Эти механизмы оказывают определенное влияние на объявления перегруженных функций. (Using-объявления и using-директивы рассматривались в разделе 8.6.)
Каким образом using-объявление сказывается на перегрузке функций? Напомним, что оно вводит псевдоним для члена пространства имен в ту область видимости, в которой это объявление встречается. Что делают такие объявления в следующей программе?
namespace libs_R_us {
int max( int, int );
int max( double, double );
extern void print( int );
extern void print( double );
}
// using-объявления
using libs_R_us::max;
using libs_R_us::print( double ); // ошибка
void func()
{
max( 87, 65 ); // вызывает libs_R_us::max( int, int )
max( 35.5, 76.6 ); // вызывает libs_R_us::max( double, double )
Первое using-объявление вводит обе функции libs_R_us::max в глобальную область видимости. Теперь любую из функций max() можно вызвать внутри func(). По типам аргументов определяется, какую именно функцию вызывать. Второе using-объявление – это ошибка: в нем нельзя задавать список параметров. Функция libs_R_us::print() объявляется только так:
using libs_R_us::print;
Using-объявление всегда делает доступными все перегруженные функции с указанным именем. Такое ограничение гарантирует, что интерфейс пространства имен libs_R_us не будет нарушен. Ясно, что в случае вызова
print( 88 );
автор пространства имен ожидает, что будет вызвана функция libs_R_us::print(int). Если разрешить пользователю избирательно включать в область видимости лишь одну из нескольких перегруженных функций, то поведение программы становится непредсказуемым.
Что происходит, если using-объявление вводит в область видимости функцию с уже существующим именем? Эти функции выглядят так, как будто они объявлены прямо в том месте, где встречается using-объявление. Поэтому введенные функции участвуют в процессе разрешения имен всех перегруженных функций, присутствующих в данной области видимости:
#include string
namespace libs_R_us {
extern void print( int );
extern void print( double );
}
extern void print( const string );
// libs_R_us::print( int ) и libs_R_us::print( double )
// перегружают print( const string )
using libs_R_us::print;
void fooBar( int ival )
{
print( "Value: "); // вызывает глобальную функцию
// print( const string )
print( ival ); // вызывает libs_R_us::print( int )
}
Using-объявление добавляет в глобальную область видимости два объявления: для print(int) и для print(double). Они являются псевдонимами в пространстве libs_R_us и включаются в множество перегруженных функций с именем print, где уже находится глобальная print(const string ). При разрешении перегрузки print в fooBar рассматриваются все три функции.
Если using-объявление вводит некоторую функцию в область видимости, в которой уже имеется функция с таким же именем и таким же списком параметров, это считается ошибкой. С помощью using-объявления нельзя задать псевдоним для функции print(int) в пространстве имен libs_R_us, если в глобальной области видимости уже есть print(int). Например:
namespace libs_R_us {
void print( int );
void print( double );
}
void print( int );
using libs_R_us::print; // ошибка: повторное объявление print(int)
void fooBar( int ival )
{
print( ival ); // какая print? ::print или libs_R_us::print
}