Если бы мы использовали оба пространства имен одновременно, то столкнулись бы с реальной проблемой. В этом случае действительно возникла бы коллизия между именами классов Text
и Line
. И что еще хуже, если бы мы были не создателями, а пользователями библиотеки, то не никак не смогли бы изменить эти имена и решить проблему. Использование пространств имен позволяет избежать проблем; иначе говоря, наш класс Text
— это класс Graph_lib::Text
, а ваш — TextLib::Text
. Имя, составленное из имени пространства имен (или имени класса) и имени члена с помощью двух двоеточий, ::
, называют
8.7.1. Объявления using и директивы using
Писать полностью определенные имена довольно утомительно. Например, средства стандартной библиотеки языка С++ определены в пространстве имен std
и могут использоваться примерно так:
#include
#include
int main()
{
std::string name;
std::cout << " Пожалуйста, введите имя \n";
std::cin >> name;
std::cout << " Привет, " << name << '\n';
}
Тысячи раз обращаясь к элементам стандартной библиотеки string
и cout
, мы на самом деле вовсе не хотим каждый раз указывать их полностью определенные имена — std::string
и std::cout
. Напрашивается решение: один раз и навсегда указать, что под классом string
мы имеем в виду класс std::string
, а под потоком cout
— поток std::cout
и т.д.
using std::string; // string означает std::string
using std::cout; // cout означает std::cout
// ...
Эта конструкция называется объявлением using
. Она эквивалентна обращению “Грэг”, которое относится к Грэгу Хансену при условии, что никаких других Грэгов в комнате нет.
Иногда мы предпочитаем ссылаться на пространство имен еще “короче”: “Если вы не видите объявления имени в области видимости, ищите в пространстве имен std”. Для того чтобы сделать это, используется директива using
.
using namespace std; // открывает доступ к именам из пространства std
Эта конструкция стала общепринятой.
#include
#include
using namespace std; // открывает доступ к именам из пространства std
int main()
{
string name;
cout << "Пожалуйста, введите имя \n";
cin >> name;
cout << "Привет, " << name << '\n';
}
Здесь поток cin
— это поток std::cin
, класс string
это класс std::string
и т.д. Поскольку мы используем заголовочный файл std_lib_facilities.h
, не стоит беспокоиться о стандартных заголовках и пространстве имен std
. Мы рекомендуем избегать использования директивы using для любых пространств имен, за исключением тех из них, которые широко известны в конкретной области приложения, например пространства имен std
. Проблема, связанная с чрезмерным использованием директивы using
, заключается в том, что мы теряем след имен и рискуем создать коллизию. Явная квалификация с помощью соответствующих имен пространств имен и объявлений using
не решает эту проблему. Итак, размещение директивы using
в заголовочный файл (куда пользователю нет доступа) — плохая привычка. Однако, для того чтобы упростить первоначальный код, мы разместили директиву using для пространства имен std
в заголовочном файле std_lib_facilities.h
. Это позволило нам написать следующий код:
#include "std_lib_facilities.h"
int main()
{
string name;
cout << "Пожалуйста, введите имя \n";
cin >> name;
cout << "Привет, " << name << '\n';
}
Мы обещаем больше никогда так не делать, если речь не идет о пространстве имен std
.
Задание
• Создайте три файла: my.h
, my.cpp
и use.cpp
. Заголовочный файл my.h
содержит следующий код:
extern int foo;
void print_foo();
void print(int);
Исходный файл my.cpp
содержит директивы #include
для вставки файлов my.h
и std_lib_facilities.h
, определение функции print_foo()
для вывода значения переменной foo
в поток cout
и определение функции print(int i)
для вывода в поток cout
значения переменной i
.