Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
шпоры по Леонову, 5семестр.doc
Скачиваний:
0
Добавлен:
01.03.2025
Размер:
503.3 Кб
Скачать

16. Пространства имён. Кратко о механизме пространства имен

Во многих современных высокоуровневых языках программирования (C++/C#, Java, Python и проч.) имеется механизм пространства имен. Он позволяет разделять определения глобальных переменных, классов или просто выполняемых функций по непересекающимся «вселенным». Каждая такая «вселенная» содержит в себе свои определения, для доступа к которым необходимо использовать специальные методы доступа. Простейшим из методов доступа является использование префикса перед именем с названием этой «вселенной» — т.е. названия этого пространства имен.

Например, в C++ используется синтаксис типа «name::var», в языке Python синтаксис типа «name.var».

В языке Си существует три жестко определенных пространства имен: глобальное для всей программы, локальное внутри модуля (статические переменные и статические функции) и локальное внутри конкретной функции. Механизм пространств имен, о котором я говорю в этой статье, позволяет разделить глобальное пространство на совокупность непересекающихся «вселенных».

К моему сожалению, язык Си за свою историю успел окостенеть настолько, что в нем уже не могут появиться столь значительные изменения, как поддержка механизма пространств имен. Пожалуй единственным прижившимся артефактом в некоторых современных реализациях языка Си для микроконтроллеров можно считать комментарии в стиле C++ — две косые черты (//).

Зачем нужен механизм пространства имен?

Говоря простым языком он наиболее удобным для программиста способом позволяет разделить глобальные переменные и функции, объявленные в разных модулях или в разных пространствах имен.

Приведу упрощенный пример. В одном проекте я использую для работы с UART модуль, который я назвал uart.c. В нем есть функция для инициализации режимов UART — пусть она будет называться init; функция для отправки байта — send; функция для чтения принятого байта — read. В другом проекте я использую модуль spi.c для работы с SPI-интерфейсом. Этот модуль также будет иметь функции для его инициализации, отправки байта и чтения байта.

В третьем проекте мне, например, будут нужны оба модуля для работы с обоими интерфейсами. Если я не приму мер, то имена функций init, send, read из этих двух модулей будут конфликтовать друг с другом. Если в распоряжении программиста имеется механизм пространства имен, то эта проблема решается достаточно просто с ее помощью. Если такого механизма нет, то приходится каждый раз выдумывать уникальные имена. Например, это могут быть InitUART, InitSPI либо uart_send, spi_read.

Имитация средствами языка Си

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

Например, для модуля uart.c будет использоваться префикс «uart_» перед именами. Для модуля spi.c этот префикс будет уже «spi_». Таким образом для вышеприведенного примера имена функций в разных модулях будут иметь следующий вид: uart_init, uart_send, uart_read; spi_init, spi_send, spi_read.

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