C++ для начинающих. Раздельная компиляция (Знакомство)

Сайт не является учебником по программированию. Это только небольшой авторский сборник информации в помощь начинающим программистам.

В этой теме затрагивается знакомство с раздельной компиляцией программ. По некоторым причинам в этой теме затрагивается возможность использования следующих материалов в среде Borland C++3.1 (Это чтобы студенты, вынужденные изучать язык в столь старой среде, не испытывали дискомфорта). Но я просто покажу как оно делается, на достаточно минимальном примере. Вся остальная часть темы будет описыватся с упорством на такие компиляторы как VS2015, clang 3.7, mingw 4.9

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

В С++ часто подключают заголовочные файлы. Мы пишем

Этим мы подключаем заголовочный файл iostream. Что в нем и как оно в нем работает, нас, как правило, не инетересует. Мы знаем, что чтобы заработала такая программа

Нужно подключить заголовочный файл iostream.

В зависимости от наших потребностей зависит включение каких-то определенных заголовочных файлов.

При создании собственных проектов такие файлы не сложно создавать самому для последующего их включения. Сейчас произойдет очень простая демонстрация создания такого файла.
По многим причинам подход раздельной компиляции программ в языке С++ очень приветствуется. Сегодня 2015г. У многих стоит Win7x64 и более новые ОС. Но некоторых жестко привязывают к старым реалиям. Поэтому я покажу создание заголовочного файла в Borland C++3.1 для тех, кто использует эмулятор dosbox

Итак. Первым делом, нужно найти саму среду Borland C++3.1
У меня она лежит в каталоге C:\Borland\
В каталоге C:\Borland\Program\ создаются исходники и в нее же компилируются программы.

Нужно найти такое место с исходниками. Надо создать там файл. Можно использовать простой блокнот и просто сохранить туда файл с кодом.
Назовем этот файл MyHeader.h

  • Код MyHeader.h

Файл с именем MyHeader.h с показанным кодом должен быть сохранен в каталог с проектом. Под проектом у нас сейчас понимается самый обычный *.cpp файл. Всё, что я делаю, просто размещаю два файла в одном месте. Теперь надо создать сам файл исходного кода.
Делаем как обычно. Кто как привык. Создаем файл. Пишем там такой код

Если все сделано правильно. Файлы *.cpp и *.h в одном месте, то этот код скомпилируется и даже запустится без нареканий.
Обратите внимание, что здесь используются не угловые скобки, а кавычки. Дело в том, что при указании кавычек, сначала файл ищется в том же каталоге где расположен проект, а потом ищется в стандартных местах для ОС. В случае указания угловых скобок файл ищется только в стандартных местах для ОС. Важно это понимать и не путать.

  • Для своих файлов — кавычки, для стандартных файлов — угловые скобки

Для современных компиляторов все это мало чем отличается. Всё то же самое. Файлы в один каталог. Компиляция *.cpp и все должно заработать. Различие только в том, что при использовании IDE (Visual Studio, CodeBlocks, DevC++ и др), не нужно добавлять имена заголовочных файлов (*.h) в список проекта. За них отвечает дирректива include.

Теперь я буду оговоривать тему, отталкиваясь от современного времени.
При использовании IDE удобно создавать заголовочные файлы с помощью меню IDE. Это такие файлы, которые обозначены как .h
Очень важно знать где расположен файл исходного кода, потому что не зная месторасположения файла исходного кода легко запутаться и сохранить файл куда-то в другой каталог. На уровень выше или наоборот в подкаталог, а обращаться к нему как будто он в каталоге с исходным кодом. Это действительно Важно понимать пока нет привычки и трудно ориентироваться.

В зависимости от ситуации может быть удобным расположить файл на уровень выше, тогда включение файла будет имет вид (В Windows)

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

    • прототипы функций
    • символические константы, определенные с использованием #define или const
    • объявления структур
    • объявления классов
    • объявления шаблонов
    • inline функции

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

Есть такое правило, что

  • Заголовочный файл должен включаться в файл только один раз

Казалось бы простое правило. Но его легко нарушить не подозревая о нарушении. Сейчас мы смоделируем ситуацию, в которой нарушим это правило.

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

Создадим проект, который состоит из двух файлов.
1. Файл исходного кода. (MyProject.cpp)
2. Заголовочный файл с объявлением структуры. (MyHeader.h)
3. Пустой заголовочный файл (OtherHeader.h) с включением в него заголовочного файла MyHeader.h

Все файлы разместим в одном месте. Если Вы создаете проект с помощью меню IDE, то надо присоеденить созданный файл MyProject.cpp к создаваемому из IDE проекту. Следующий код должен компилироваться.

  • Файл MyProject.cpp

Теперь создадим файл MyHeader.h, сохраним его в том же каталоге, где и MyProject.cpp

  • Файл MyHeader.h

Такие файлы, с расширением .h к проекту присоединять не надо. За это отвечает дирректива include.
Теперь если оба файла в одном месте и файл исходного кода MyProjec.cpp присоединен к проекту, код, показываемый ниже должен компилироваться и запуститься без нареканий.

  • Код С++. Компиляция файла со своим заголовочным файлом

Если разобрались. То создаем еще один файл. Для удобства изучения, создадим его опять же в том же каталоге.

  • Файл OtherHeader.h

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

  • Файл MyProject.cpp с включением двух файлов

Если всё получилось сделать как я пытаюсь описать, то здесь будет маленький неприятный сюрприз. Вся эта конструкция откажется компилироваться в связи с переопределением структуры MyStruct. Прежде чем понять как исправить, лучше всего разобраться в причине. Причина этому довольна проста. Когда Вы используете диррективу include, Вы этим как бы включаете все содержимое файла в файл исходного кода. Это такая операция как "Вырезать текст из заголовочного файла и вставить его в то место, где написано include".
И происходит следующий эффект.

Вот во что превращается файл MyProject.cpp

 
 
=========>

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

 
 
=========>

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

  • В C/C++ существует стандартный прием, позволяющий избежать многократных включений заголовочных файлов. Он основан на использовании директивы препроцессора #ifndef (if not defined — если не определено)

Все значимое содержимое заголовочных файлов помещается вовнутрь специальной защитной конструкции

Таким образом, чтобы заставить работать показанный проект, нужно защитить его специальной защитной конструкцией. Меняем файл MyHeader.h

  • Код С++ Заголовочный файл MyHeader.h

Теперь проект скомпилируется и запустится. Да, он ничего не делает. Но так должно быть понятнее. Если бы в файле OtherHeader.h содержались значимые объявления, то и их надо было защитить таким способом. Просто внутри него пусто, поэтому переопределений возникнуть не может.

Будем надеяться, что эта тема описана достаточно подробно, понятно и действительно помогает в изучении С++.

Все комментарии на сайте проверяются, поэтому ваш комментарий может появиться не сразу. Для вставки кода в комментарий используйте теги: [php]ВАШ_КОД[/php]

Добавить комментарий

Ваш e-mail не будет опубликован.

Поиск

 
     

Яндекс.Метрика

НАГРАДИ АВТОРА САЙТА
WEBMONEY
R375024497470
U251140483387
Z301246203264
E149319127674

Работа программиста и шамана имеет много общего - оба бормочут непонятные слова, совершают непонятные действия, и не могут объяснить, как оно работает

Выражаю свою признательность

  • Максиму очень признателен за указание на мои ошибки и неточности.
  • Sergio ===> за оказание помощи в исправлении моих ошибок
  • Gen ===> за правильное стремление помочь другим новичкам и выявления моих ошибок