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

Преимущества только для заголовков

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

4b9b3361

Ответ 1

Существуют ситуации, когда единственная опция только для библиотеки заголовка, например, при работе с шаблонами.

Наличие библиотеки только для заголовков также означает, что вам не нужно беспокоиться о разных платформах, где может использоваться библиотека. Когда вы отделяете реализацию, вы обычно делаете это, чтобы скрыть детали реализации, и распределите библиотеку в виде комбинации заголовков и библиотек (файлы lib, dll или .so). Они, конечно же, должны быть скомпилированы для всех различных операционных систем/версий, которые вы предлагаете.

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

Конечно, это применяется в каждом конкретном случае. Например, библиотеки только для заголовков иногда увеличивают время компиляции code size &.

Ответ 2

Преимущества библиотеки только для заголовков:

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

Недостатки библиотеки только для заголовков:

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

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

  • Более запутанная компиляция. Вы получаете намного больше зависимостей от библиотеки только для заголовков из-за этих дополнительных #include, необходимых для библиотеки только заголовка. Измените реализацию некоторой ключевой функции в библиотеке, и вам, возможно, потребуется перекомпилировать весь проект. Внесите это изменение в исходный файл для скомпилированной библиотеки, и все, что вам нужно сделать, это перекомпилировать исходный файл библиотеки, обновить скомпилированную библиотеку с этим новым .o файлом и повторно подключить приложение.

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

Ответ 3

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

Ответ 4

Я знаю, что это старый поток, но никто не упоминает интерфейсы ABI или специфические проблемы компилятора. Поэтому я думал, что буду.

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

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

Например, поставщики компиляторов часто меняют свою реализацию STL между версиями. Если у вас есть функция в библиотеке, которая принимает std::vector, тогда она ожидает, что байты в этом классе будут упорядочены так, как они были организованы при компиляции библиотеки. Если в новой версии компилятора поставщик улучшил эффективность до std::vector, тогда код пользователя увидит новый класс, который может иметь другую структуру и передает эту новую структуру в вашу библиотеку. Оттуда все идет вниз... Вот почему рекомендуется не пропускать объекты STL через границы библиотек. То же самое относится к типам C Run-Time (CRT).

Говоря об ЭЛТ, ваша библиотека и исходный код пользователя обычно должны быть связаны с одним и тем же ЭЛТ. С Visual Studio, если вы создаете свою библиотеку с помощью многопотокового CRT, но пользователь связывается с многопоточным CRT-отладчиком, у вас будут проблемы с ссылками, потому что ваша библиотека может не найти нужные ей символы. Я не помню, какая функция была, но для Visual Studio 2015 Microsoft сделала одну встроенную CRT-функцию. Внезапно это было в заголовке, а не в библиотеке CRT, поэтому библиотеки, которые ожидали найти их в момент ссылки, больше не могли делать, и это порождало ошибки ссылок. В результате эти библиотеки нуждались в перекомпиляции с Visual Studio 2015.

Вы также можете получить ошибки ссылок или странное поведение, если используете Windows API, но вы создаете с различными настройками Unicode для пользователя библиотеки. Это связано с тем, что в Windows API есть функции, в которых используются строки Unicode или ASCII и макросы /, которые автоматически используют правильные типы, основанные на настройках Unicode проекта. Если вы передадите строку по границе библиотеки, которая является неправильным типом, тогда все происходит во время выполнения. Или вы можете обнаружить, что программа не ссылается в первую очередь.

Эти вещи также верны для передачи объектов/типов через границы библиотек из других сторонних библиотек (например, вектора Eigen или матрицы GSL). Если сторонняя библиотека изменяет свой заголовок между компиляцией библиотеки и вашим компилятором своего кода, тогда все будет нарушено.

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

Если вы предоставляете только библиотеку с заголовком, тогда весь код скомпилируется с теми же настройками компилятора и против одних и тех же заголовков, поэтому многие из этих проблем уходят (предоставление версии третьей частичной библиотеки, которую вы и ваш пользователь использует, совместимы с API).

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