Кодирование С++ (в основном) в файлах заголовков vs .cpp файлов
В течение многих лет я кодировал С++ стандартным образом, с объявлениями классов в файлах заголовков .hpp и определениях функций в исходных файлах .cpp. Недавно я переехал в новую компанию, где код (по-видимому, под влиянием стилей форсированного кодирования) полностью закодирован в .hpp файлах с одним коротким файлом .cpp для включения файлов заголовков и создания двоичного файла объекта/программы.
Это заставило меня задуматься - каковы сильные/слабые стороны написания кода в файлах заголовков, а не для записи файлов .hpp и .cpp для каждого объекта? Это предполагает, что наш проект не создает общие библиотеки, которые затем связаны в программные двоичные файлы, но вместо этого каждый программный двоичный файл создается из суммы файлов заголовков (и одного исходного файла .cpp). Является ли это новой тенденцией в С++?
например. Объекты шаблонов должны быть только заголовками, но может показаться хорошей идеей разместить классы без шаблонов в заголовочных файлах, а затем просто включить эти общие классы проектов в свои двоичные файлы. Предполагая, что вы создаете новую кодовую базу с нуля, означало бы это меньше ссылок, что могло бы означать меньше ссылок на ошибки и, возможно, более быстрые сборки. Были ли предварительно скомпилированные объекты заголовков также означать, что файлы заголовков ускоряют время сборки? Или время сборки больше, потому что теперь нам нужно скомпилировать весь код при создании двоичного файла, а не связывать общие объекты общей библиотеки?
Также обратите внимание, что здесь мы не пишем API (в этом случае что-то вроде идиомы pimpl даст нам больше гибкости, скрывая реализацию), мы пишем программы для запуска на сайте клиента.
Спасибо заранее,
Ответы
Ответ 1
Сверху моей головы:
Сильные стороны:
- реализация видима (более слабость, но зависит от случая)
- нет необходимости экспортировать в библиотеку
- лучший шанс для компилятора оптимизировать часть кода
Слабые стороны:
- видимость реализации
- более медленное время сборки
- взломанные файлы заголовков
- изменение в реализации потребует полной перестройки, если реализация в файле реализации не выполняется (только компилируйте этот конкретный файл или библиотеку)
- В случае круговых зависимостей вы используете forward-declarations и включаете только полный тип в файл реализации. Если все, что у вас есть, это заголовок, это уже невозможно.
Я уверен, что есть другие, я отредактирую, если буду думать о них больше.
Ответ 2
Библиотеки только для заголовков, как правило, упрощают создание системы сборки, и в целом вам нужно меньше заботиться о зависимостях.
С другой стороны, перемещение кода в файлы реализации облегчает управление границами модулей и создает обменные двоичные модули, которые могут улучшить инкрементные сборки. Стоимость более "домашнего хозяйства".
Моя догадка состоит в том, чтобы предпочесть файлы реализации, и есть некоторые точки данных, которые поддерживают меня, например это сообщение в блоге от автора предлагаемого Boost Networking Библиотека.
Ответ 3
Общие библиотеки - это одно, общее повторное использование кода - другое. Если вы хотите использовать какой-то код, который вы написали в другом проекте, вам, возможно, придется копировать "огромные куски кода", а затем поддерживать отдельные кодовые базы. Время компиляции будет увеличиваться, потому что программа будет одним большим компилятором, а не многими файлами cpp/h, где только эти, которые включают измененный файл заголовка, будут перекомпилированы. Например, полная сборка приложения, над которым я сейчас работаю, занимает 7 минут. Повторная компиляция занимает ~ пятнадцать секунд, если изменения не являются серьезными. Наконец, код может быть менее читаемым. Файл заголовка дает вам быстрый взгляд на то, для чего создан класс и как его использовать. Если классы написаны на месте, вам придется неоправданно прорыть исходный код.