src/ folder structure in C++?
i’m coming into C++ from Java/AS3-land, and i’m used to the package-cum-folder structure for my classes. and i like it.
i understand the very basics of namespaces in c++, and i’m happy to leave it at just the basics. but, as my project gets more complex, i’d like to keep my folder structure organized in a way i can keep in my head. i.e. something similar to Java/AS3.
1) is there any reason to not have a folder structure like:
possibly with subfolders? (this is just an MVC example, the folder structure could be whatever depending on the project’s needs.) it just seems unruly to have a src/ folder with a huge pile of header and source files within.
2) if the answer to 1) could be «go ahead and do what you want», would it be unwise/unnecessary to create a namespace for each folder, similar to Java/AS3’s way of creating a package for each folder? my understanding is that namespaces are not usually used like this, nested deeply and folder-related.
6 Answers 6
I’ve always liked the namespace for each folder. Mostly because when I have to maintain somebody else’s code, the namespace helps me find where the class was originally defined.
Well named header files can also help with this though. I also wouldn’t suggest going more than 2-3 namespaces, as then it just becomes obnoxious. You’ll find yourself using «using namespace blah;» a lot which I always find to be a red flag for C++ code. And you can’t use «using namespace» inside a header file without some severe problems occurring.
It’s all completely optional though in C++.
You may want to have a look at John Lakos Large-Scale C++ Software Design . Basically, you can do that, but your packages should (as in Java) have an acyclic dependency graph. Also, it may be opportune for each package to document which headers are exported and which aren’t, maybe like so:
Each package is only allowed to #include the top-level headers of another package, never ones in src/ directories.
Also, when you want to use Autotools in a large project and intend to distribute headers, it may prove to be prudent to call the top-level directory not src/ but by the PACKAGE_TARNAME of that project. This makes installing headers with the help of the Autotools easier.
(And, of course, the actual file names do not look as silly as illustrated above.)
There’s no reason not to divide your source code into different directories; it makes sense if there are many files and clear logical groupings.
It is not necessary to create a distinct file for each small class though — in large projects, that tends to slow compilation (as the implementation files often have to include a lot of the same headers just to compile their couple dozen lines).
As well as the use of namespaces for reflecting the logical divisions in the code, the exact thresholds at which code is subdivided into further namespaces tends to be driven by some other forces, for example:
- factors suggesting use of more namespaces
- very volatile code (often edited, constant additional/changed identifier use, often short and/or common words)
- more developers
- tight coordination by a central body
- planned formal releases with thorough checks for conflicts
Namespaces can also be used as a way to allow easy switching between alternative implementations (e.g. different versions of a protocol, thread-safe versus unsafe support functions, OS-specific implementations), so sometimes catering for such needs involves use of distinct namespaces.
It can definitely be painful digging through unintuitive and/or deeply nested namespaces to reach the variables you want, and «using namespace» is less effective if you’re likely to need to use several that define the same identifiers anyway, but can suit more modal code that tends to use one or the other namespace more heavily at a time.
So, you may want to consider these factors when deciding whether to put each folder’s code (or some other logically distinct group) into distinct namespaces.
Src что это c
I’m studying an example of operators and references. In the code, there is a public constructor that has this syntax:
Point(const Point &src)
Can anybody explain to me what «src» is doing? Is this an abbreviation for «source»?


Got it. I didn’t realize that «src» was just a variable name chosen by the programmer. I was thinking that it was something more formal.
src / структура папок на C++?
Я прихожу в C++ из Java / AS3-land, и я привык к структуре пакетов и папок для своих классов. и мне это нравится.
Я понимаю самые основы пространств имен в c++, и я рад оставить его только в основах. но, поскольку мой проект становится все сложнее, я бы хотел, чтобы структура папок была организована так, чтобы я мог держать ее в голове. т. е. что-то похожее на Java/AS3.
1) Есть ли основания не иметь структуру папок например:
возможно с подпапками? (это просто пример в MVC структура папок может быть любой в зависимости от потребностей проекта.) просто кажется неуправляемым иметь src / папку с огромной кучей заголовочных и исходных файлов внутри.
2) если ответ на 1) может быть «идти вперед и делать то, что вы хотите», было бы неразумно/ненужно создавать пространство имен для каждой папки, подобно способу Java/AS3 создания пакета для каждой папки? в моем понимании эти пространства имен обычно не используются так, вложенные глубоко и связанные с папками.
6 ответов
Мне всегда нравилось пространство имен для каждой папки. В основном потому, что когда я должен поддерживать чей-то код, пространство имен помогает мне найти, где класс был первоначально определен.
хорошо названные файлы заголовков также могут помочь с этим. Я также не предложил бы идти больше, чем 2-3 пространства имен, так как тогда это просто становится неприятным. Вы обнаружите, что используете «использование пространства имен blah;» много, что я всегда нахожу красным флагом для кода C++. И вы не можете использовать «using namespace» внутри файла заголовка без каких-либо серьезных проблем.
Это все совершенно необязательно, хотя в C++.
возможно, вы захотите взглянуть на Джон Лакос Large-Scale C++ Software Design . В принципе, вы можете это сделать, но ваши пакеты должны (как в Java) иметь график ациклических зависимостей. Кроме того, для каждого пакета может быть удобно документировать, какие заголовки экспортируются, а какие нет, может быть так:
каждому пакету разрешено только #включать заголовки верхнего уровня другого пакета, никогда не в src/ справочники.
кроме того, когда вы хотите использовать Autotools в большом проекте и намереваясь распространять заголовки, может оказаться разумным называть каталог верхнего уровня не src/ , а PACKAGE_TARNAME этого проекта. Это делает установку заголовков с помощью Autotools легче.
(и, конечно, фактические имена файлов не выглядят так глупо, как показано выше.)
src / является общим местом, где программисты c / C++ помещают свои источники в корень проекта. Например:
обычно создаются подкаталоги под src/, если у вас много исходных файлов, но нет ограничений на организацию этой подструктуры.
имейте в виду, что структура каталогов полностью необязательна в c++. Это не связь между пространствами имен c++ и структурой каталогов.
нет причин не разделять исходный код на разные каталоги; это имеет смысл, если есть много файлов и четкие логические группировки.
нет необходимости создавать отдельный файл для каждого небольшого класса, хотя-в больших проектах, что, как правило, замедляет компиляцию (поскольку файлы реализации часто должны включать много одинаковых заголовков, чтобы скомпилировать их пару десятков строк).
а также использование пространств имен для отражения логической деления в коде, точные пороговые значения, при которых код подразделяется на дальнейшие пространства имен, как правило, управляются некоторыми другими силами, например:
- факторы, предлагающие использовать больше пространств имен
- очень изменчивый код (часто редактируемый, постоянный дополнительный/измененный идентификатор, часто короткие и/или общие слова)
нет причин не делать этого и действительно поможет людям, читающим ваш код. Некоторые вещи, чтобы следить за:
- не над-nest папки, это может быть запутанным для читателей вашего кода.
- будьте последовательны в организации вашего кода, например, не поставить любой Просмотр кода в подкаталоге контроллеры или наоборот.
- сохранить макет в чистоте.
вы можете организовать ваши файлы, как вам нравится; вам просто нужно настроить инструменты сборки » включают пути и исходные пути для соответствия.
предоставление каждому каталогу собственного пространства имен является излишним и, вероятно, плохой идеей, поскольку это приведет к путанице кода. Я бы рекомендовал не более одного пространства имен для каждого проекта или даже только одно пространство имен для каждой компании (поскольку, предположительно, в вашей компании у вас есть возможность переименовывать вещи, если это необходимо для разрешения конфликтов имен. Основные пространства имен цель состоит в том, чтобы обработать случай, когда две кодовые базы под управлением двух разных организаций используют одно и то же имя, и вы как третья сторона хотите использовать их в одном проекте, но не имеете возможности изменить ни одну кодовую базу).
Русские Блоги
Роль make-файла состоит в том, чтобы компилировать код проекта и управлять им, экономить время, затрачиваемое на компиляцию проекта, и извлекать выгоду из продолжительности написания одного раза.
И поскольку цель создается позже, чем зависимость, после обновления зависимости будет обнаружена цель или время генерации зависимости, поэтому даже при изменении программы .c команда make используется для повторного запуска make-файла (запустите make-файл, используя команду Результат, отображаемый командой make, может быть результатом изменения программы (рабочего механизма make-файла).
Есть три основных элемента для создания make-файла: цели, зависимости и команды. Целевой объект относится к целевому файлу, который будет создан в make-файле.
Зависимость относится к файлу, который используется для создания целевого файла (то есть целевой файл создается зависимостью). Команда относится к команде, которая генерирует целевой файл по зависимости (то есть целевой файл может быть получен зависимостью с помощью этой команды, если быть точным, команда gcc генерирует целевой файл из зависимости к цели)
В make-файле три основных содержимого, которые, как правило, можно описать, две функции и три автоматические переменные.

Правило
Это правило называется шаблонным правилом, которое относится к:
В цели и зависимости в make-файле один или несколько% могут быть включены в цель, и зависимость также может включать%, а значение% в условии зависимости зависит от% в цели, другими словами, Значения, представленные% в зависимой и целевой, должны быть равны.
Две функции
src = $ (подстановочный знак * .c) функция
Его функция — найти файлы .c в целевом файле и назначить их все src (то есть файл .c хранится в src, а src в этой функции является переменной с произвольным именем, но $ (подстановочный знак.c) — это функция make-файла этой реализации для поиска файла .c), следует отметить, что в этой функции подстановочный знак иМежду .c нет запятой, чтобы разделить их, между ними есть только пробел)
obj = $ (patsubst% .c,% .o, $ (src)) функция
Его функция состоит в том, чтобы заменить файл .c в суффиксе на файл .o и назначить его obj, извлечь третий набор параметров и заменить все части, содержащие первый параметр, на часть второго параметра (т. Е. , Obj хранит объектный файл .o), где obj — это переменная с произвольным именем, а $ (patsubst% .c,% .o, $ (src)) — это реализация этого для преобразования файла .c в .o Функция makefile для файла. Следует отметить, что в этой функции нет запятой между patsubst и% .c для их разделения, между ними есть только пробел, а между% .c,% .o и $ (src) используется запятая. Отдельно.
Три автоматические переменные
В make-файле есть три автоматические переменные, а именно
В дополнение к этому одному правилу, двум функциям и трем правилам в make-файле, есть также чистый, и определение переменных в make-файле и значения переменных также являются важным содержанием.
Чистый формат не имеет зависимостей только от целевого объекта.В команде clean вы можете написать команду для удаления целевого файла и окончательного файла. (В make-файле оговаривается, что, когда есть только целевой файл и нет зависимостей, соответствующая команда под этой целью будет выполняться напрямую) После того, как make-файл записан, когда здесь должна быть выполнена чистка, команда выполняется Это сделать чистым.
Команда make clear -n (-n означает имитацию выполнения команды clear в следующем make-файле, просто чтобы показать команду в make-файле, а она фактически не выполняется).
В чистой цели вам необходимо использовать оператор псевдо-цели. Этот оператор псевдо-цели означает, что, когда текущий путь содержит файл или каталог с командой clean, когда используется команда make clean, результат не может быть выполнен, и Подскажет "чистая последняя".
Чтобы решить эту проблему, вам нужно всего лишь добавить в make-файл оператор псевдо-цели в формате .PHONY.clean


В дополнение к трем автоматическим переменным, которые поставляются с make-файлом, вы также можете вручную настроить переменные. Метод адресации переменной, определенной в make-файле: $ (имя переменной), значение, присвоенное переменной здесь, может быть файлом .c или файлом .o
Конкретное создание make-файла
(Предположим, что есть три функции, используемые для реализации функций сложения, вычитания и умножения в add.c mul.c sub.c и основная функция)
1. Создайте make-файл
Имя файла созданного первым makefile может быть makefile или Makefile, команда для создания файла — vi makefile или vi Makefile.
2. Напишите правила зависимости
Цель: зависимая
(расстояние в одну табуляцию) командаВторая строка gcc — это команда для реализации цели из зависимости
или это могло быть
Здесь следует отметить, что make-файл читается сверху вниз, и первая строка файла является конечной целью. Поэтому поместите цель и зависимости конечного исполняемого файла в первую строку make-файла.
Используйте пользовательские переменные для компиляции
Используйте makefile три пользовательские переменные для компиляции
Компилировать с использованием переменных, хранящихся в make-файле
Используйте функции, предоставляемые make-файлом, для компиляции
Используйте makefile для компиляции файлов в разных каталогах
Предположим теперь, что файл .c помещен в каталог src, файл .h помещен в каталог include, а файл .o, который должен быть скомпилирован, помещен в obj, диаграмма каталогов выглядит следующим образом:
Makefile на данный момент должен быть написан так:
Расширить знания
Описание опции Makefile CFLAGS, LDFLAGS, LIBS
CFLAGS представляет собой опции для компилятора C
CXXFLAGS представляет параметры для компилятора C ++
Эти две переменные фактически охватывают два этапа компиляции и сборки.CFLAGS: укажите путь к файлу заголовка (.h), например: CFLAGS = -I / usr / include -I / path / include.
Точно так же, когда пакет установлен, включаемая папка будет создана по пути установки.Если во время процесса установки произойдет сбой, попробуйте добавить в эту переменную включаемую папку ранее установленного пакета.
- LDFLAGS: некоторые параметры оптимизации, используемые компиляторами, такими как gcc, также могут указывать расположение файлов библиотеки.
Как использовать: LDFLAGS = -L / usr / lib -L / путь / к / вашему / lib. Каждый раз при установке пакета в папке установки почти создается папка lib. Предположим, что определенный пакет явно установлен, а когда установлен другой пакет, он сообщает, что не может его найти. Попробуйте выполнить это с помощью LDFALGS, который может указать путь к библиотеке этого пакета.
- LIBS: Сообщите компоновщику, какие файлы библиотеки нужно связать. Например, LIBS = -lpthread -liconv
Проще говоря, LDFLAGS сообщает компоновщику, где искать файлы библиотеки, а LIBS сообщает компоновщику, какие файлы библиотеки нужно связать.
Иногда LDFLAGS указывает -L, хотя это позволяет компоновщику найти библиотеку для компоновки. Но компоновщик среды выполнения не может найти эту библиотеку. Предполагая, что путь к файлу библиотеки во время выполнения программного обеспечения также расширен, нам нужно добавить эти две библиотеки в «-Wl, R»:
Предположим, вы установили переменную среды export LDFLAGS = ”- L / var / xxx / lib -L / opt / mysql / lib -Wl, R / var / xxx / lib -Wl, R / opt / mysql / lib во время работы ./configure ", обратите внимание, что в параметрах переменной среды не может быть пробелов по обе стороны от знака равенства, и следует добавить кавычки (как использовать оболочку). Затем после запуска configure. Makefile установит эту опцию. При компоновке будет этот параметр, а путь поиска файла библиотеки скомпилированной исполняемой программы будет расширен.
Используйте динамические библиотеки в Linux
Я рассказал, как скомпилировать с помощью Makefile, но проблематично ссылаться на динамическую библиотеку после компиляции. Например, программа интегрирует динамическую библиотеку x264, но динамическую библиотеку невозможно найти при ее вызове. Это неприятная вещь. Три решения.
Например, динамическая библиотека x264 находится в каталоге / home / username / x264build / lib.
- Добавьте LD__LIBRARY_PATH в переменные среды пользователя (обычно не используются)
Добавление местоположения динамической библиотеки в переменную пользовательской среды может иметь постоянный эффект (пока динамическая библиотека все еще находится в этом месте), например, переменная пользовательской среды в ubuntu находится в /home/username/.profile
После настройки перезапустите терминал
- Добавьте путь динамической библиотеки к временному пути (для тестирования)
Этот метод входит прямо в терминал
В это время динамическая библиотека будет временно импортирована в переменную окружения. Недостатком является то, что ее нельзя использовать, когда терминал закрыт.