Пространства имен. Ключевые слова namespace, using. Правила создания пространства имен. Глобальное пространство имен
Содержание
- 1. Понятие пространства имен. Объявление пространства имен. Ключевое слово namespace. Задание именованного и неименованного пространства имен
- 2. Пример объявления и использования пространства имён. Все элементы размещаются в одном модуле
- 3. Директива using. Доступ к элементам пространства имен
- 4. Глобальное пространство имен ::
- 5. Повторное объявление пространства имен. Пример
- 6. Объявление пространства имен в разных файлах (модулях)
- 7. Пространство имен std
- 8. Вложенные пространства имен
Поиск на других ресурсах:
1. Понятие пространства имен. Объявление пространства имен. Ключевое слово namespace. Задание именованного и неименованного пространства имен
До появления пространств имен использовалось одно единое глобальное пространство. Это пространство содержало список общедоступных глобальных переменных и функций, которые можно было использовать в своей программе. Если в программе объявлялись собственные функции, чьи имена совпадали с именами функций глобального пространства имен (например, функции abs(), sqrt() и т.п.), то имена этих локальных функций перекрывали глобальные. Это вызывало неудобства и требовало более внимательного отношения к выбору имен. Также проблема выбора имен возникала при одновременном использовании нескольких сторонних библиотек.
Чтобы упростить использование имен в приложениях на C++, было введено понятие пространства имен. Пространство имен – это область определения переменных, типов, констант и функций, объединенная в единый или неименованный блок. Пространство имен обозначается с использованием ключевого слова namespace и в наиболее общем случае объявляется следующим образом:
namespace Name { // Объявление переменных, констант, типов, функций // ... }
После объявления пространства имен можно обращаться к его элементам. Имя пространства имен можно не указывать, если это имя объявлено в этом же пространстве имен.
За пределами пространства имен обращение выглядит следующим образом
Name::item
де
- Name – имя пространства имен;
- item – имя элемента (функции, класса, константы, переменной) который объявлен в пространстве имен.
Пространство имен может быть объявлено без имени по следующему синтаксису
namespace { // составляющие пространства имен // ... }
С точки зрения размещения пространство имен может быть объявлено:
- в одном модуле;
- в нескольких модулях (см. примеры ниже).
⇑
2. Пример объявления и использования пространства имён. Все элементы размещаются в одном модуле
В примере объявляется пространство имен MATH, содержащее следующие объявления:
- константа Pi;
- функция Circumference() – возвращает длину окружности на основе заданного радиуса;
- функция AreaCircle() – возвращает площадь круга на основе заданного радиуса;
- функция VolumeSphere() – возвращает объем шара на основе заданного радиуса.
В функции main() демонстрируется доступ к некоторым составляющим пространства имен MATH.
#include <iostream> using namespace std; // Пространство имен MATH namespace MATH { // Константа в пространстве имен const double Pi = 3.1415; // Функция, возвращающая длину окружности double Circumference(double r) { return 2 * Pi * r; } // Функция, возвращающая площадь круга double AreaCircle(double r) { return Pi * r * r; } // Функция, возвращающая объем шара double VolumeSphere(double r) { return 4.0 / 3 * Pi * r * r * r; } } void main() { cout << "Pi = " << MATH::Pi << endl; cout << "V = " << MATH::VolumeSphere(3) << endl; }
⇑
3. Директива using. Доступ к элементам пространства имен
С целью повышения читабельности программы и избегания постоянного указания имени пространства имен при доступе к его элементам используется директива using. Эта директива может применяться в двух случаях:
using namespace Name; // подключение пространства имен using Name::member; // подключение отдельного элемента
здесь
- Name – имя пространства имен;
- member – имя элемента пространства имен. Элементом могут быть константа, функция, класс и т.д.
В первом случае подключается все пространство имен. После подключения доступ к элементам этого пространства имен можно производить непосредственно без указания фрагмента Name::.
Во втором случае подключается отдельный элемент пространства имен. После подключения можно указать непосредственно имя этого элемента без задания фрагмента Name::.
⇑
3.1. Пример доступа ко всем элементам пространства имен
В примере объявляется пространство имен MATH. Затем, в целях демонстрации, это пространство имен подключается с помощью строки
using namespace MATH;
В теле функции main() происходит обращение к составляющим пространства имен MATH (константа Pi, функция VolumeSphere()). Обращение происходит без указания префикса MATH::.
#include <iostream> using namespace std; // Пространство имен MATH namespace MATH { // Константа в пространстве имен const double Pi = 3.1415; // Функция, возвращающая длину окружности double Circumference(double r) { return 2 * Pi * r; } // Функция, возвращающая площадь круга double AreaCircle(double r) { return Pi * r * r; } // Функция, возвращающая объем шара double VolumeSphere(double r) { return 4.0 / 3 * Pi * r * r * r; } } using namespace MATH; void main() { // Обращение к составляющим пространства имен MATH // без указания MATH:: cout << "Pi = " << Pi << endl; cout << "V = " << VolumeSphere(3) << endl; }
Результат выполнения программы
Pi = 3.1415 V = 113.094
⇑
3.2. Пример доступа к отдельному элементу в пространстве имен
В примере объявляется пространство имен Operations и показывается доступ к методам Sub2() и Mul2() этого пространства из функции main().
#include <iostream> using namespace std; // Пространство имен, в котором определены базовые операции над двумя числами namespace Operations { double Add2(double a, double b) { return a + b; } double Sub2(double a, double b) { return a - b; } double Mul2(double a, double b) { return a * b; } double Div2(double a, double b) { if (b == 0) return 0; return a / b; } } // Реализовать доступ к методам Sub2() и Mul2() using Operations::Sub2; using Operations::Mul2; void main() { double x = 10, y = 8; double z = Sub2(x, y); // z = 2 cout << "z = " << z << endl; z = Mul2(x, y); cout << "z = " << z << endl; // Ошибка, нету доступа // z = Add2(x, y); // identifier Add2 is undefined }
Результат выполнения программы
z = 2 z = 80
В вышеприведенном примере подключение методов осуществляется директивой using с помощью строк
using Operations::Sub2; using Operations::Mul2;
После этого эти методы могут быть вызваны непосредственно без использования префикса Operations::. Если попытаться вызвать неподключенный метод Add2()
// Ошибка, нету доступа
z = Add2(x, y);
то компилятор выдаст сообщение об ошибке
identifier Add2 is undefined
⇑
4. Глобальное пространство имен ::
Глобальное пространство имен определяет область видимости самого высокого уровня. В данной области видимости могут быть объявлены глобальные переменные, типы, функции и т.д.
Для доступа к глобальному пространству имен необходимо использовать оператор расширения области видимости ::. Если в глобальном пространстве имен и в некотором локальном пространстве есть совпадающие имена, то для доступа к глобальному имени использование оператора :: обязательно.
Пример.
В примере объявляется:
- глобальная функция ShowPi(), выводящая значение числа Пи;
- пространство имен MathItems, содержащее некоторые константы и функцию ShowPi(), имя которой совпадает с именем глобальной функции.
В функции main() демонстрируется доступ к одноименным функциям.
#include <iostream> using namespace std; // Глобальная функция, выводящая значение числа Pi void ShowPi() { cout << "Pi = 3.1415" << endl; } // Пространство имен, в котором определены константы и функции namespace MathItems { const double Pi = 3.1415; const double E = 2.71828; // Функция, которая отображает значение числа Pi из пространства имен void ShowPi() { cout << "MathItems::Pi = " << Pi << endl; } } using namespace MathItems; void main() { // 1. Вызов глобальной функции ShowPi() ::ShowPi(); // 2. Вызов функции ShowPi() из пространства имен MathItems MathItems::ShowPi(); // 3. Ошибка - неоднозначный вызов перегруженной функции //ShowPi(); // ambiguous call to overloaded function }
Результат выполнения программы
Pi = 3.1415 MathItems::Pi = 3.1415
Если в вышеприведенном коде в функции main() попробовать реализовать вызов
// Ошибка - неоднозначный вызов
ShowPi();
то компилятор сгенерирует ошибку
ambiguous call to overloaded function
Это логично, поскольку неизвестно, к какой функции ShowPi() происходит обращение.
⇑
5. Повторное объявление пространства имен. Пример
Пространство имен может состоять из частей. Эти части могут быть объявлены в одном или нескольких модулях. В наиболее общем случае разбиение пространства имен выглядит следующим образом
namespace Name { // Часть 1. Описание составляющих // ... } namespace Name { // Часть 2. Описание составляющих // ... } ... namespace Name { // Часть N. Описание составляющих // ... }
Пример.
В примере реализовано пространство имен Operations с несколькими функциями. Это пространство имен разбито на 2 части.
#include <iostream> using namespace std; // Пространство имен, которое определяет базовые операции над двумя числами namespace Operations { double Add2(double a, double b) { return a + b; } double Sub2(double a, double b) { return a - b; } } namespace Operations { double Mul2(double a, double b) { return a * b; } double Div2(double a, double b) { if (b == 0) return 0; return a / b; } } void main() { // Вызов функций из разных частей пространства имен Operations cout << Operations::Add2(5, 8) << endl; cout << Operations::Mul2(5, 8) << endl; }
⇑
6. Объявление пространства имен в разных файлах (модулях)
Пространство имен может быть разбито на несколько файлов. Иными словами, объявление пространства имен и их составляющих может быть в разных файлах. В наиболее общем случае объявление пространства имен с именем Name в разных файлах выглядит следующим образом:
Файл 1.
using namespace Name { // Составляющие пространства имен в файле 1 // ... }
Файл 2.
using namespace Name { // Составляющие пространства имен в файле 2 // ... }
Файл N.
using namespace Name { // Составляющие пространства имен в файле N // ... }
Пример.
Пусть заданы два модуля:
- модуль Source.cpp, содержащий объявление первой части пространства имен Operations и функцию main();
- модуль Operations.h, в котором объявляется вторая часть пространства имен Operations.
В этом случае текст обоих пространств имен следующий.
Модуль Source.cpp.
#include <iostream> #include "Operations.h" using namespace std; // Пространство имен, в котором определены базовые операции // над двумя числами, первая часть пространства имен namespace Operations { double Add2(double a, double b) { return a + b; } double Sub2(double a, double b) { return a - b; } } void main() { // Вызов функций из разных частей пространства имен Operations // Из текущего модуля cout << Operations::Add2(5, 8) << endl; // Из модуля Operations.h cout << Operations::Mul2(5, 8) << endl; }
Модуль Operations.h.
#pragma once // Вторая часть пространства имен Operations namespace Operations { double Mul2(double a, double b) { return a * b; } double Div2(double a, double b) { if (b == 0) return 0; return a / b; } }
⇑
7. Пространство имен std
В классическом C++ базовым пространством имен есть пространство имен std. В этом пространстве имен реализуются средства стандартной библиотеки C++.
В стандартной библиотеке реализовано тысячи функций, которые полезны при разработке любых программ. Примерами таких функций могут служить математические функции abs(), acos(), sin(), cos() и другие. Подробное рассмотрение возможностей стандартной библиотеки C++ не является предметом обсуждения данной темы.
В предыдущих версиях C++ вся стандартная библиотека была в глобальном пространстве имен. Помещение стандартной библиотеки в пространство имен std существенно снижает возможность конфликтов имен.
Для подключения пространства имен std используется строка
using namespace std;
Также часто в программах встречается обращение к элементам пространства имен std с указанием полного имени, например
// корень квадратный double a = std::sqrt(28); // модуль числа int x; x = std::abs(-18);
⇑
8. Вложенные пространства имен
Пространства имен могут быть вложенными. Это означает, что одно пространство имен может включать другое пространство имен. В этом случае к вложенному пространству имен и его составляющим можно получить доступ обычным способом с помощью оператора ::.
Пример.
В примере объявляется два пространства имен:
- OUT – это внешнее пространство имен;
- IN – это пространство имен, которое вложено в пространство имен OUT.
В функции main() демонстрируется доступ к составляющим пространств имен OUT и IN.
#include <iostream> using namespace std; // Вложенные пространства имен namespace OUT { void MethodOut() { } int var_out; namespace IN { int var_in = var_out; void MethodIn() { MethodOut(); var_out = 3; cout << "var_out = " << var_out << endl; } } } void main() { // использование оператора :: OUT::IN::var_in = 35; OUT::IN::MethodIn(); // после такой строки using namespace OUT; IN::var_in = 333; cout << "IN::var_in = " << IN::var_in << endl; // после такой строки using namespace OUT::IN; MethodIn(); // можно обращаться к методу непосредственно }
Результат выполнения программы
var_out = 3 IN::var_in = 333 var_out = 3
⇑