АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомДругоеЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

Многофайловые программы. Межфайловое взаимодействие переменных

Читайте также:
  1. Алекс сидел за ограждением позади сцены, где фанатов не было, и давал интервью для какой-то программы.
  2. Бактериофаги. Взаимодействие фага с бактериальной клеткой. Умеренные и вирулентные бактериофаги. Лизогения.
  3. Взаимодействие в месте приложения действия.
  4. Взаимодействие валеологии с другими науками
  5. Взаимодействие внутри большой семьи
  6. Взаимодействие государства и права
  7. ВЗАИМОДЕЙСТВИЕ ГОСУДАРСТВА С ПОЛИТИЧЕСКИМИ ПАРТИЯМИ И ИНЫМИ ОБЪЕДИНЕНИЯМИ ГРАЖДАН
  8. Взаимодействие гребного винта и корпуса судна. Пропульсивный коэффициент
  9. Взаимодействие дефектов кристаллического строения
  10. Взаимодействие досуга и рекреации.
  11. Взаимодействие зарядов. Закон Кулона. Закон сохранение электрического заряда.
  12. Взаимодействие заряженных тел. Закон Кулона. Закон сохранения электрического заряда.

Межфайловое взаимодействие

В многофайловых программах элементы, хранящиеся в разных файлах, должны
каким-то образом сообщаться друг с другом. В этом разеделе мы выясним, как
это делается. Вначале мы обсудим, как сообщаются откомпилированные по от-
дельности, но скомпонованные вместе исходные файлы (.cpp), а затем — как об-
ращаться с заголовочными (.H) файлами.

Взаимодействие исходных файлов

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

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

Межфайловые переменные

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

Большинство объявлений являются также и определениями. Точнее, единст-
венным объявлением простой переменной, не являющимся определением, явля-
ется объявление с использованием зарезервированного слова extern (без ини-
циализации):

int SomeVar; //объявление и определение в одном флаконе

extern int someVar; //только объявление

 

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

 

//файл A

int globalvar; //определение в файле A
//файл В

int globalVar; //как НЕЛЬЗЯ делать: то же определение в
//файле B

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

Как же обеспечить доступ к глобальным переменным, находящимся в одном
файле, из другого? Тот факт, что компоновщик будет воротить нос при попытке

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

//файл A

int globalVar; //Определение в файле A
//файл В

globalVar=3; //НЕЛЬЗЯ! globalVar тут никто не знает

Компилятор справедливо заметит, что globalVar — неидентифицированный
идентификатор.

Чтобы то, что мы так рекламировали в начале этого пункта, было действи-
тельно правдой, то есть чтобы переменная, определенная в одном файле, была
видна в другом, нужно объявлять ее во всех остальных файлах с помощью заре-
зервированного слова extern.

//файл A

int globalVar; //Определение в файле A
//файл В

extern int globalVar; //Объявление в файле B

globalVar = 3; //Вот теперь все хорошо

Как вы уже, наверное, догадались, объявление глобальной переменной в фай-
ле A сделало ее видимой в файле B, Зарезервированное слово extern означает,
что объявление в данном случае — это только объявление, ничего более. Оно
просит компилятор, который в каждый момент времени видит только один файл,
не обращать внимание на то, что переменная globalVar не определена в файле B.
Компоновщик, который с высоты своего особого статуса обозревает все файлы
проекта, позаботится об установке ссылки на переменную, не определенную
в данном файле.

Необходимо помнить об одном, возможно, неожиданном, ограничении: пере-
менную нельзя инициализировать в объявлении с extern. Выражение


extern int globalVar = 27; //не то, что вы имеете в виду

 

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

Но что, если вам действительно никак не прожить без глобальных перемен-
ных с одинаковыми именами в разных файлах? В этом случае необходимо опре-
делять их с помощью зарезервированного слова static. Тем самым область види-
мости глобальной переменной сужается до файла, в котором она определена.
Другие переменные с тем же именем могут в других файлах использоваться без
ограничений,


//файл A

static int globalVar; //определение: переменная видна
//только в A

//файл В

static int globalVar; //определение: переменная видна

//только в В

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

В многофайловых программах мы рекомендуем делать глобальные перемен-
ные статическими, если по логике работы к ним не требуется доступ более чем
из одного файла. Это предотвратит возникновение ошибки, связанной со слу-
чайным заданием того же имени переменной в другом файле. К тому же лис-
тинг в этом случае становится более прозрачным — не нужно заботиться о про-
верке разных файлов на предмет совпадения имен.

Обратите внимание, что зарезервированное слово static имеет несколько зна-
чений в зависимости от контекста. В главе 5 «Функции» мы обсуждали, что ког-
да static изменяет локальную переменную (то есть определенную внутри функ-
ции), изменяется ее продолжительность жизни от функции до всей программы,
но видимость сохраняется неизменной, ограниченной функцией. Как уже говори-
лось в главе 6 «Объекты и классы», компонентные данные статических классов
имеют одинаковое значение для всех объектов, а не для каждого — свое. Однако
в контексте глобальных переменных слово static просто сужает область видимо-
сти до одного файла.

Переменная, определенная с помощью const, в общем случае не видна за пре-
делами одного файла. В этом смысле она такая же, как static. Но ее можно сде-
лать видимой из любого файла программы и для определения, и для объявле-
ния с помощью слова extern:

//файл A

extern const int conVar2 = 99; //определение

//файл В

extern const int conVar2; //объявление

Здесь файл В будет иметь доступ к переменной conVar2, определенной в фай-
ле A. Компилятор различает объявление и определение константы по наличию
или отсутствию инициализации.


1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 |

Поиск по сайту:



Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Студалл.Орг (0.005 сек.)