Стандарты программирования на С++. 101 правило и рекомендация | страница 103



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

Однако директивы и объявления >using предназначены только для вашего удобства и вы не должны использовать их так, чтобы они влияли на какой-то другой код. В частности, их нельзя употреблять где попало, где за ними может следовать еще какой-то сторонний код. В частности, их не следует использовать в заголовочных файлах (которые предназначены для включения в неограниченное количество файлов реализации — вы не должны вносить путаницу в значение кода в этих файлах) или перед директивой >#include (тем самым вы по сути вносите их в текст этих заголовочных файлов).

Большинство программистов интуитивно понимают, почему директива >using (например, >using namespace A;) вызывает загрязнение в случае воздействия на код, следующий за ней и не осведомленный о наличии этой директивы: поскольку эта директива полностью импортирует одно пространство имен в другое, включая даже те имена, которые до сих пор не были видны, понятно, что это может легко изменить смысл следующего за директивой кода.

Но вот одна распространенная ошибка: многие считают, что использование объявления >using на уровне пространства имен (например, >using N::Widget;) вполне безопасно. Однако это не так. Такие объявления, как минимум, опасны, причем более тонким и хитрым способом. Рассмотрим следующий код:

>// Фрагмент 1

>namespace A {

> int f(double);

>}


>// Фрагмент 2

>namespace B {

> using A::f;

> void g();

>}


>// Фрагмент 3

>namespace A {

> int f(int);

>}


>// Фрагмент 4

>void В::g() {

> f(1); // какая перегрузка будет вызвана?

>}

Здесь опасность заключается в том, что объявление >using использует текущий список имен >f в пространстве имен в тот момент, когда это объявление встречается. Таким образом, какая именно перегрузка будет видима в пространстве имен , зависит от того, где именно находится приведенный код фрагментов и в каком порядке он скомбинирован. (Здесь должен раздаться предупреждающий рев вашей внутренней сирены — "Зависимость от порядка есть зло!") Вторая перегрузка, >f(int), в большей степени соответствует вызову