Мы показали, как связаны using-объявления и перегруженные функции. Теперь рассмотрим особенности применения using-директивы. Using-директива приводит к тому, что члены пространства имен выглядят объявленными вне этого пространства, добавляя их в новую область видимости. Если в этой области уже есть функция с тем же именем, то происходит перегрузка. Например:
#include string
namespace libs_R_us {
extern void print( int );
extern void print( double );
}
extern void print( const string );
// using-директива
// print(int), print(double) и print(const string ) - элементы
// одного и того же множества перегруженных функций
using namespace libs_R_us;
void fooBar( int ival )
{
print( "Value: "); // вызывает глобальную функцию
// print( const string )
print( ival ); // вызывает libs_R_us::print( int )
}
Это верно и в том случае, когда есть несколько using-директив. Одноименные функции, являющиеся членами разных пространств, включаются в одно и то множество:
namespace IBM {
int print( int );
}
namespace Disney {
double print( double );
}
// using-директива
// формируется множество перегруженных функций из различных
// пространств имен
using namespace IBM;
using namespace Disney;
long double print(long double);
int main() {
print(1); // вызывается IBM::print(int)
print(3.1); // вызывается Disney::print(double)
return 0;
}
Множество перегруженных функций с именем print в глобальной области видимости включает функции print(int), print(double) и print(long double). Все они рассматриваются в main() при разрешении перегрузки, хотя первоначально были определены в разных пространствах имен.
Итак, повторим, что перегруженные функции находятся в одной и той же области видимости. В частности, они оказываются там в результате применения using-объявлений и using-директив, делающих доступными имена из других областей.
9.1.5. Директива extern "C" и перегруженные функции A
В разделе 7.7 мы видели, что директиву связывания extern "C" можно использовать в программе на C++ для того, чтобы указать, что некоторый объект находится в части, написанной на языке C. Как эта директива влияет на объявления перегруженных функций? Могут ли в одном и том же множестве находиться функции, написанные как на C++, так и на C?
В директиве связывания разрешается задать только одну из множества перегруженных функций. Например, следующая программа некорректна:
// ошибка: для двух перегруженных функций указана директива extern "C"
extern "C" void print( const char* );
extern "C" void print( int );
Приведенный ниже пример перегруженной функции calc() иллюстрирует типичное применение директивы extern "C":
class SmallInt ( /* ... */ );
class BigNum ( /* ... */ );
// написанная на C функция может быть вызвана как из программы,
// написанной на C, так и из программы, написанной на C++.
// функции C++ обрабатывают параметры, являющиеся классами
extern "C" double calc( double );
extern SmallInt calc( const SmallInt );
extern BigNum calc( const BigNum );
Написанная на C функция calc() может быть вызвана как из C, так и из программы на C++. Остальные две функции принимают в качестве параметра класс и, следовательно, их допустимо использовать только в программе на C++. Порядок следования объявлений несуществен.
Директива связывания не имеет значения при решении, какую функцию вызывать; важны только типы параметров. Выбирается та функция, которая лучше всего соответствует типам переданных аргументов:
Smallint si = 8;
int main() {
calc( 34 ); // вызывается C-функция calc( double )
calc( si ); // вызывается функция C++ calc( const SmallInt )
// ...