Подтвердить что ты не робот

Каковы преимущества относительного пути, например "../include/header.h" для заголовка?

Я рассмотрел вопросы правильно использовать директиву include и С++ #include semantics, и ни один из адресов это - и другие, предложенные SO, когда я набрал название...

Что, если таковые имеются, являются преимуществами написания:

#include "../include/someheader.h"
#include "../otherdir/another.h"

по сравнению с использованием простого имени файла:

#include "someheader.h"
#include "another.h"

или, возможно, относительное имя без '..':

#include "include/someheader.h"
#include "otherdir/another.h"

Я вижу следующие проблемы:

  • Вы не можете перемещать заголовок, не беспокоясь о том, какие исходные файлы включают его.
  • Вы можете получить очень длинные пути для заголовков в зависимостях и отчетах об ошибках. Сегодня у меня был "../dir1/include/../../include/../dir2/../include/header.h".

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

Итак, я не вижу преимущества?


Спасибо за входные данные. Я думаю, что консенсус в том, что нет никаких существенных преимуществ для нотации, использующей "..", которую я пропускаю. В общем, мне нравится нотация "где-то/header.h"; Я использую его в новых проектах. Тот, над которым я работаю, не что иное, как новый.

Одна из проблем заключается в том, что существуют различные группы заголовков, часто с префиксом, таким как rspqr.h, rsabc.h, rsdef.h, rsxyz.h. Все они связаны с кодом в каталоге rsmp, но некоторые заголовки находятся в rsmp, а другие находятся в центральной директории include, в которой нет подкаталогов, таких как rsmp. (И повторите для разных других областей кода, есть заголовки в нескольких местах, которые необходимо случайным образом выполнять с помощью других битов кода.) Перемещение материала вокруг является серьезной проблемой, потому что код стал настолько запутанным на протяжении многих лет. И make файлы несовместимы, в которых предусмотрены опции -I. В целом, это печальная история о не столь благожелательном пренебрежении в течение нескольких десятилетий. Фиксировать все это, не нарушая ничего, будет долгой, утомительной работой.

4b9b3361

Ответ 1

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

#include "Physics/Solver.h"

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

Я почти никогда не использую синтаксис "..", хотя вместо этого у меня в моем проекте указаны правильные базовые местоположения.

Ответ 2

Проблема с #include "../include/header.h" заключается в том, что она часто срабатывает случайно, а затем, казалось бы, не связанное с ней изменение заставит ее перестать работать позже.

Например, рассмотрим следующий макет источника:

./include/header.h
./lib/library.c
./lib/feature/feature.c

И скажем, что вы используете компилятор с пуском include -I. -I./lib. Что происходит?

  • ./lib/library.c может сделать #include "../include/header.h", что имеет смысл.
  • ./lib/feature/feature.c также может выполнять #include "../include/header.h", хотя это не имеет смысла. Это связано с тем, что компилятор попытается установить директиву #include относительно местоположения текущего файла, и если это не удастся, он попытается установить директиву #include относительно каждой записи -I в пути #include.

Кроме того, если вы позже удалите -I./lib из пути #include, вы разломете ./lib/feature/feature.c.

Я считаю предпочтительным следующее:

./projectname/include/header.h
./projectname/lib/library.c
./projectname/lib/feature/feature.c

Я бы не добавлял никаких добавленных записей пути, кроме -I., а затем library.c и feature.c использовал бы #include "projectname/include/header.h". Предполагая, что "имя проекта", вероятно, будет уникальным, это не должно приводить к столкновениям имен или неоднозначностям в большинстве случаев. Вы также можете использовать путь include и/или сделать функцию VPATH, чтобы разделить физический макет проекта на несколько каталогов, если это абсолютно необходимо (например, для размещения специально созданного для конкретной платформы кода - это то, что действительно ломается, когда вы используйте #include "../../somefile.h").

Ответ 3

IANALL, но я не думаю, что вы должны размещать .. в реальных исходных файлах C или С++, потому что это не портативный, а стандарт не поддерживает его. Это похоже на использование \ в Windows. Делайте это только в том случае, если ваш компилятор не может работать с каким-либо другим способом.

Ответ 4

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

Я бы избегал таких путей, как:

  • "include/foo/bar.h" - "include" кажется нелогичным и избыточным
  • "../foo/bar.h" - ".." предполагает относительное местоположение и хрупкое.
  • "bar.h" - если bar.h не находится в текущем каталоге, это загрязняет глобальное пространство имен и запрашивает неоднозначность.

Лично я склоняюсь к тому, что в мои проекты добавляется следующий путь: path - "..;../..;../../..;../../../..".

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

Я склонен полностью квалифицировать #include в публичных заголовках, поэтому третьим лицам, покупающим мой код, не нужно добавлять "..;../..;../../..;../../../.." к их проекту - это просто удобство для моего личного кода и системы сборки.

Ответ 5

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

Ответ 6

Еще одна проблема с окнами с относительными путями - MAX_PATH. Это вызовет проблемы компиляции, когда, например, кросс-компиляция для android, и ваш путь увеличивается больше 260.