Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии 


Глава 20: Пространства имен и другие темы




В этой главе описаны пространства имен и такие эффективные средства, как explicit-конструкторы, указатели на функции, static-члены, const-функции-члены, альтернативный синтаксис инициализации членов класса, операторы указания на члены, ключевое слово asm, спецификация компоновки и функции преобразования.

Пространства имен

Пространство имен определяет некоторую декларативную область.

Пространства имен мы кратко рассмотрели в главе 2. Они позволяют локализовать имена идентификаторов, чтобы избежать конфликтных ситуаций с ними. В С++-среде программирования используется огромное количество имен переменных, функций и имен классов. До введения пространств имен все эти имена конкурировали за память в глобальном пространстве имен, что и было причиной возникновения многих конфликтов. Например, если бы в вашей программе была определена функция toupper(), она могла бы (в зависимости от списка параметров) переопределить стандартную библиотечную функцию toupper(), поскольку оба имени должны были бы храниться в глобальном пространстве имен. Конфликты с именами возникали также при использовании одной программой нескольких библиотек сторонних производителей. В этом случае имя, определенное в одной библиотеке, конфликтовало с таким же именем из другой библиотеки. Подобная ситуация особенно неприятна при использовании одноименных классов. Например, если в вашей программе определен класс VideoMode, и в библиотеке, используемой вашей программой, определен класс с таким же именем, конфликта не избежать.

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

Понятие пространства имен

Ключевое слово namespace позволяет разделить глобальное пространство имен путем создания некоторой декларативной области. По сути, пространство имен определяет область видимости. Общий формат задания пространства имен таков.

namespace name {

 // объявления

}

Все, что определено в границах инструкции namespace, находится в области видимости этого пространства имен.

В следующей программе приведен пример использования namespace-инструкции. Она локализует имена, используемые для реализации простого класса счета в обратном направлении. В созданном здесь пространстве имен определяется класс counter, который реализует счетчик, и переменные upperbound и lowerbound, содержащие значения верхней и нижней границ, применяемых для всех счетчиков.

namespace CounterNameSpace {

 int upperbound;

 int lowerbound;

 class counter {

   int count;

  public:

   counter(int n) {

    if(n <= upperbound) count = n;

    else count = upperbound;

   }

   void reset(int n) {

    if(n <= upperbound) count = n;

   }

   int run() {

    if(count > lowerbound) return count--;

    else return lowerbound;

   }

 };

}

Здесь переменные upperbound и lowerbound, а также класс counter являются частью области видимости, определенной пространством имен CounterNameSpace.

В любом пространстве имен к идентификаторам, которые в нем объявлены, можно обращаться напрямую, т.е. без указания этого пространства имен. Например, в функции run(), которая находится в пространстве имен CounterNameSpace, можно напрямую обращаться к переменной lowerbound:

if(count > lowerbound) return count--;

Но поскольку инструкция namespace определяет область видимости, то при обращении к объектам, объявленным в пространстве имен, извне этого пространства необходимо использовать оператор разрешения области видимости. Например, чтобы присвоить значение 10 переменной upperbound из кода, который является внешним по отношению к пространству имен CounterNameSpace, нужно использовать такую инструкцию.

CounterNameSpace::upperbound = 10;

Чтобы объявить объект типа counter вне пространства имен CounterNameSpace, используйте инструкцию, подобную следующей.

CounterNameSpace::counter ob;

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

Рассмотрим программу, в которой демонстрируется использование пространства имен CounterNameSpace.

// Демонстрация использования пространства имен.

#include <iostream>

using namespace std;

namespace CounterNameSpace {

 int upperbound;

 int lowerbound;

 class counter {

   int count;

  public:

   counter (int n) {

    if(n <= upperbound) count = n;

    else count = upperbound;

   }

   void reset (int n) {

    if(n <= upperbound) count = n;

   }

   int run() {

    if(count > lowerbound) return count--;

    else return lowerbound;

   }

 };

}

Int main()

{

 CounterNameSpace::upperbound = 100;

 CounterNameSpace::lowerbound = 0;

 CounterNameSpace::counter ob1(10);

 int i;

 do {

  i = ob1.run();

  cout << i << " ";

 }while(i > CounterNameSpace :: lowerbound);

 cout << endl;

 CounterNameSpace::counter ob2(20);

 do {

  i = ob2.run();

  cout << i << " ";

 }while(i > CounterNameSpace::lowerbound);

 cout << endl;

 ob2.reset(100);

 CounterNameSpace::lowerbound = 90;

 do {

  i = ob2.run();

  cout << i << " ";

 }while(i > CounterNameSpace::lowerbound);

 return 0;

}

Обратите внимание на то, что при объявлении объекта класса counter и обращении к переменным upperbound и lowerbound используется имя пространства имен CounterNameSpace. Но после объявления объекта типа counter уже нет необходимости в полной квалификации его самого или его членов. Поскольку пространство имен однозначно определено, функцию run() объекта ob1 можно вызывать напрямую, т.е. без указания (в качестве префикса) пространства имен (ob1.run()).

Программа может содержать несколько объявлений пространств имен с одинаковыми именами. Это означает, что пространство имен можно разбить на несколько файлов или на несколько частей в рамках одного файла. Вот пример.

namespace NS {

 int i;

}

 // . . .

namespace NS {

 int j;

}

Здесь пространство имен NS разделено на две части. Однако содержимое каждой части относится к одному и тому же пространству имен NS.

Любое пространство имен должно быть объявлено вне всех остальных областей видимости. Это означает, что нельзя объявлять пространства имен, которые локализованы, например, в рамках функции. При этом одно пространство имен может быть вложено в другое.

Инструкция using

Инструкция using делает заданное пространство имен "видимым", т.е. действующим.

Если программа включает множество ссылок на члены некоторого пространства имен, то нетрудно представить, что необходимость указывать имя этого пространства имен при каждом к ним обращении, очень скоро утомит вас. Эту проблему позволяет решить инструкция using, которая применяется в двух форматах.

using namespace имя;

using name::член;

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

using CounterNameSpace::lowerbound; /* Видимым стал только член lowerbound */

lowerbound = 10; /* Все в порядке, поскольку член lowerbound находится в области видимости. */





Рекомендуемые страницы:


Читайте также:

Последнее изменение этой страницы: 2016-03-17; Просмотров: 262; Нарушение авторского права страницы


lektsia.com 2007 - 2018 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.014 с.) Главная | Обратная связь