Урок 20. Многофайловые программы

  Юрий Ворон  | 

    | 

  Обновлено 5 Ноя 2018  | 

 17934

 ǀ   20 

Как только программы становятся больше – их следует разделять на несколько файлов, в организационных и функциональных целях. Одним из преимуществ работы в IDE является легкость при работе с n-ым количеством файлов. Вы уже знаете, как создавать и компилировать однофайловые проекты, а добавление новых также не составит труда.

Добавление файлов в проект. Visual Studio

В Visual Studio щелкните правой кнопкой мыши на Source Files в Solution Explorer и выберите Add > New Item. Убедитесь, что у вас выбран C++ File (.cpp). Дайте новому файлу имя и он добавится в ваш проект.

Примечание: Если вы создаете новый файл из меню File, а не в Solution Explorer, то он не добавится к вашему проекту автоматически. Нужно будет подключать вручную. Для этого нужно щелкнуть правой кнопкой мыши на Source Files в Solution Explorer, выбрать Add > Existing Item, а затем выбрать нужный файл.

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



Добавление файлов в проект. Code::Blocks

В Code::Blocks перейдите в меню File и выберите New file. Дайте новому файлу имя (не забудьте расширение .cpp), затем Code::Blocks спросит вас, желаете ли вы добавить его к активному проекту. Нажмите Yes. Вам также нужно будет поставить галочки возле Release и Debug, дабы убедиться, что файл добавится к обеим версиям.

Если Code::Blocks не спросит вас о добавлении файла в активный проект или если файл не отобразится в панели проекта – нужно будет добавлять вручную. Для этого щелкните правой кнопкой мыши по имени проекта в панели проекта, выберите Add File, найдите только что созданный файл и добавьте его.

Теперь, при компиляции программы, новый файл будет автоматически добавлен, так как он является частью проекта.

Если новый файл не компилируется или не проходит линкинг в Code::Blocks, убедитесь, что он подключен для компиляции и линкинга. Для этого щелкните правой кнопкой мыши по файлу в панели проекта и выберите Properties. На вкладке General вы увидите чекбоксы, возле которых должны быть галочки (они указывают на то, будет ли файл подключен к компиляции и линкингу). Убедитесь, что галочки поставлены.

Добавление файлов в проект. Командная строка

В командной строке вы можете создать дополнительный файл и дать ему имя самостоятельно, используя редактор. При компиляции программы, вам необходимо будет подключить все соответствующие файлы с кодом. Например: g++ main.cpp add.cpp -o main (где main.cpp и add.cpp – это имена файлов с кодом, а main — это имя выходного файла).

Пример многофайловой программы

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

add.cpp:

main.cpp:

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

add.cpp(10) : error C3861: 'add': identifier not found
add.cpp(15) : error C2365: 'add' : redefinition; previous definition was 'formerly unknown identifier'

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

Тем не менее, в данном случае, мы хотим, чтобы main.cpp знал (и использовал) функцию аdd(), которая находится в add.cpp. Для предоставления доступа main.cpp к функции add, мы можем использовать предварительное объявление.

main.cpp с предварительным объявлением:

Теперь, когда компилятор скомпилирует main.cpp, он будет знать, что такое add(). Используя этот метод, мы можем предоставлять доступ одним файлам к функциям, которые находятся в других файлах.

Попробуйте скомпилировать add.cpp и main.cpp с предварительным объявлением сами. Если получите ошибку линкера, убедитесь, что вы добавили add.cpp к вашему проекту.



Что-то пошло не так!

Есть много вещей, которые могут пойти не так, в первый раз, когда вы попытаетесь работать с несколькими файлами. Возникли проблемы? Проверьте следующее:

1. Если вы получили ошибку компилятора, что add() не определен в main(), вы, вероятно, забыли записать предварительное объявление в main.cpp.

2. Если вы получили ошибку линкера о том, что add не определен, например:

unresolved external symbol "int __cdecl add(int,int)" (?add@@YAHHH@Z) referenced in function _main

то возможных решений есть несколько:

наиболее вероятной причиной является то, что add.cpp не корректно добавлен в ваш проект. Если вы используете Visual Studio или Code::Blocks, вы должны увидеть add.cpp в Solution Explorer или в панели проекта IDE. Если нет, то щелкните правой кнопкой мыши по вашему проекту и добавьте файл, а затем повторите попытку компиляции. Если вы проводите компиляцию с помощью командной строки — не забудьте подключить как main.cpp, так и add.cpp.

вполне возможно, что вы добавили add.cpp к другому проекту.

вполне возможно, что файл не подключен к компиляции или линкингу. Проверьте свойства файла и убедитесь, что поставлены галочки возле пунктов о компиляции/линкинге файла. В Visual Studio есть еще опция «exclude from build» (исключить из сборки), которая должна быть установлена на «нет» или оставлена пустой.

3. Если вы используете Visual Studio с предварительно откомпилированными заголовками, каждый файл кода должен иметь строчку: #include "stdafx.h". Как main.cpp, так и add.cpp.

4. Не пишите строчку: #include "add.cpp" в main.cpp. Это приведет к тому, что компилятор вставит содержимое add.cpp непосредственно в main.cpp вместо того, чтобы рассматривать их как отдельные файлы. Даже если это скомпилируется сейчас, позднее вы будете постоянно сталкиваться с проблемами, используя этот способ.

Напоследок

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

Напоминание: Всякий раз, когда вы создаете новый файл кода (.cpp) — добавляйте его в свой проект.

Оценить статью:

Звёзд: 1Звёзд: 2Звёзд: 3Звёзд: 4Звёзд: 5 (159 оценок, среднее: 4,78 из 5)
Загрузка...

Комментариев: 20

  1. данила:

    не получается разделить функцию main() на 2 файла (без возвратных функций)…это вообще возможно?)

  2. Александр:

    После беглого просмотра десятка-другого уроков понял, что уроки-то неплохие (не считая некоторых грамматических ошибок), да вот возникло стойкое чувство deja vu. И правда, как оказалось, этот курс — просто перевод с минимальными изменениями курса, представленного на сайте LearnCpp.com.
    И хотя я искренне считаю, что людям, не владеющим английским языком, в программировании категорически делать нечего, все же ничего не имею против переводов хороших источников.
    Но только если автор честно пишет, что это не его детище, а просто перевод. Я не смог найти никакого упоминания или ссылки на оригинал. Мало того, вы, Юрий, еще и пытаетесь денег на этом заработать, продавая книжку с этим добром. Если я ошибся, прошу прощения, но если нет, то это очень грустно.

    1. Юрий Ворон Юрий Ворон:

      А где же, Александр, я писал, что это моё детище? Моё детище — это сайт Ravesli, а уроки С++ — это перевод. На странице "Уроки С++" пролистайте до конца — там источник уроков.

      Насчет денег — да, пытаюсь. Только перевод, а не оригинал, да ещё и с "минимальными изменениями". Уроки по С++ останутся бесплатными на сайте до тех пор, пока я буду поддерживать этот сайт, а всё что дополнительно — то это уже на моё усмотрение.

      1. Александр:

        Тогда я ошибся, и это чудесно =) Прошу прощения. Я не заметил ссылки, привык их искать где-то в аннотации.

        1. Юрий Ворон Юрий Ворон:

          Ничего, без проблем 🙂

  3. Леонид:

    Добрый день! При попытке добавить в функцию, которая находится в отдельном файле, "stdafx.h" компилятор выдаёт ошибку: не удаётся открыть файл включения stdafx.h: No such file or directory. Без stdafx.h всё нормально работает. Visual Studio 2015.

    1. Юрий Юрий:

      Скорее всего у вас отключены предварительно скомпилированные заголовки, коим и является stdafx.h. Работает без него — хорошо, работает с ним — еще лучше.

  4. Марина:

    Сегодня читала статью с телефона. Очень удобный сайт)

    1. Юрий Юрий:

      Можно и с телефона, и с планшета, и с компьютера, и с ноутбука — лишь бы желание было, а возможность предоставим 🙂

  5. Илья:

    Когда пишу файл add.cpp постоянно не идёт,это ж линкер мешает по моему???И что ему не так,когда твою программу скопировал,также всё:

    Ошибка LNK2019 ссылка на неразрешенный внешний символ _main в функции "int __cdecl invoke_main(void)" (?invoke_main@@YAHXZ) add.cpp 1

    1. Юрий Юрий:

      Вы сделали всё как в уроке? Правильно добавили файл? К тому проекту, что нужно?

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

  6. Максим():

    Почему в VS нужно обязательно подключать библиотеку stdafx.h? Раньше, когда я учился по видеоурокам, я писал программы и без ее подключения. Но конечно есть одно но, я тогда немного изменил параметры создания проекта: поставил галочку на "Empty project" и удалил галочку на "Security Development Lifecycle (SDL) checks ". Может быть это как-то повлияло?

    1. Юрий Юрий:

      stdafx.h — это реализация механизма «предварительно скомпилированных заголовков», который используется для ускорения процесса сборки проектов. В этом файле содержатся вызовы других библиотек и заголовочных файлов, которые нужны для корректного выполнения ваших программ. Т.е. чтобы не прописывать дополнительно подключение определенных библиотек и заголовочных файлов — эти вызовы записали в одном файле и подключают только stdafx.h (1 строчка кода), а не прописывают дополнительно 20 строчек #include. Но от этого можно увидеть толк и почувствовать реальную пользу, когда ваши проекты состоят минимум из десятка файлов.

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

      Отключается stdafx.h в Visual Studio так: Project (Проект) -> Properties (Свойства) -> C/C++ -> Precompiled Headers (Предварительно скомпилированные заголовки) и выбираете пункт «Not using Precompiled Files» (сокр. «Не использовать»).

      По поводу того, как повлияли галочки возле «Empty Project» и «Security Development Lifecycle checks» на отключение механизма «предварительно скомпилированных заголовков» я ничего не могу сказать.

  7. Андрей Оганесян:

    Зачем писать названия в VS (например Source Files) на английском, если в VS есть русский язык?

    1. Li4ik Li4ik:

      Это уже дело вкуса, кому как привычнее.

      1. Андрей Оганесян:

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

        1. Li4ik Li4ik:

          Хотите вы этого или нет, но английский, даже самый базовый, знать вам придется. Любые команды, ключевые слова и прочее в коде — это обычные английские слова, которые имеют определенные значения. Писать транслитом (русские слова английской раскладкой) названия файлов, переменных, функций, классов — это, как минимум, некрасиво и неудобно. Что тут делать? Учить английский.

        2. Данила:

          +)).. тоже в гугл лез)))

      2. Андрей Оганесян:

        Согласен, спасибо

        1. Li4ik Li4ik:

          Понимаю, полным новичкам могут быть непонятны некоторые слова, но от этого никуда не деться. Там, где можно упростить — я упрощаю, что можно перевести — я перевожу, но всё перевести нельзя. Сам синтаксис любого языка программирования — это английский. И тут уже нужно подстраиваться.

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

Ваш e-mail не будет опубликован. Обязательные поля помечены *