Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++ для начинающих (Стенли Липпман) 3-е хххх.pdf
Скачиваний:
86
Добавлен:
30.05.2015
Размер:
5.92 Mб
Скачать

С++ для начинающих

419

переменная bk скрывает blip::bk. Ссылка на bk внутри manip() не является неоднозначной речь идет о локальной переменной.

Using-директивы использовать очень просто: стоит написать одну такую директиву, и все члены пространства имен сразу становятся видимыми. Однако чрезмерное увлечение ими

namespace cplusplus_primer { class matrix { };

// прочие вещи ...

}

namespace DisneyFeatureAnimation { class matrix { };

// здесь тоже ...

using namespace cplusplus_primer; using namespace DisneyFeatureAnimation;

matrix m; //ошибка, неоднозначность:

возвращает нас к старой проблеме засорения глобального пространства имен:

// cplusplus_primer::matrix или DisneyFeatureAnimation::matrix?

Ошибки неоднозначности, вызываемые using-директивой, обнаруживаются только в момент использования. В данном случае при употреблении имени matrix. Такая ошибка, найденная не сразу, может стать сюрпризом: заголовочные файлы не менялись и никаких новых объявлений в программу добавлено не было. Ошибка появилась после того, как мы решили воспользоваться новыми средствами из библиотеки.

Using-директивы очень полезны при переводе приложений на новые версии библиотек, использующие пространства имен. Однако употребление большого числа using-директив возвращает нас к проблеме засорения глобального пространства имен. Эту проблему можно свести к минимуму, если заменить using-директивы более селективными using- объявлениями. Ошибки неоднозначности, вызываемые ими, обнаруживаются в момент объявления. Мы рекомендуем пользоваться using-объявлениями, а не using-директивами, чтобы избежать засорения глобального пространства имен в своей программе.

8.6.4. Стандартное пространство имен std

Все компоненты стандартной библиотеки С++ находятся в пространстве имен std. Каждая функция, объект и шаблон класса, объявленные в стандартном заголовочном файле, таком, как <vector> или <iostream>, принадлежат к этому пространству.

Если все компоненты библиотеки объявлены в std, то какая ошибка допущена в данном примере:

С++ для начинающих

420

#include <vector> #include <string> #include <iterator>

int main()

{

//привязка istream_iterator к стандартному вводу istream_iterator<string> infile( cin );

//istream_iterator, отмечающий end-of-stream istream_iterator<string> eos;

//инициализация svec элементами, считываемыми из cin vector<string> svec( infile, eos );

//...

}

Правильно, этот фрагмент кода не компилируется, потому что члены пространства имен std должны использоваться с указанием их специфицированных имен. Для того чтобы исправить положение, мы можем выбрать один из следующих способов:

заменить имена членов пространства std в этом примере соответствующими специфицированными именами;

применить using-объявления, чтобы сделать видимыми используемые члены пространства std;

употребить using-директиву, сделав видимыми все члены пространства std.

Членами пространства имен std в этом примере являются: шаблон класса istream_iterator, стандартный входной поток cin, класс string и шаблон класса vector.

Простейшее решение добавить using-директиву после директивы препроцессора #include:

using namespace std;

В данном примере using-директива делает все члены пространства std видимыми. Однако не все они нам нужны. Предпочтительнее пользоваться using-объявлениями,

чтобы уменьшить вероятность коллизии имен при последующем добавлении в программу глобальных объявлений.

using std::istream_iterator; using std::string;

using std::cin;

Using-объявления, необходимые для компиляции этого примера, таковы: using std::vector;

Но куда их поместить? Если программа состоит из большого количества файлов, можно для удобства создать заголовочный файл, содержащий все эти using-объявления, и

включать его в исходные файлы вслед за заголовочными файлами стандартной библиотеки.

С++ для начинающих

421

В нашей книге мы не употребляли using-объявлений. Это сделано, во-первых, для того, чтобы сократить размер кода, а во-вторых, потому, что большинство примеров компилировались в реализации С++, не поддерживающей пространства имен. Подразумевается, что using-объявления указаны для всех членов пространства имен std, используемых в примерах.

Упражнение 8.14

Поясните разницу между using-объявлениями и using-директивами.

Упражнение 8.15

Напишите все необходимые using-объявления для примера из раздела 6.14.

Упражнение 8.16

namespace Exercise { int ivar = 0; double dvar = 0;

const int limit = 1000;

}

int ivar = 0;

//1

void manip() { //2

double dvar = 3.1416; int iobj = limit + 1; ++ivar;

++::ivar;

Возьмем следующий фрагмент кода:

}

Каковы будут значения объявлений и выражений, если поместить using-объявления для всех членов пространства имен Exercise в точку //1? В точку //2? А если вместо using- объявлений использовать using-директиву?