Мне нравится концепция DRY (не повторяйте себя [oops]), но концепция заголовочных файлов С++ противоречит этому правилу программирования. Есть ли недостаток в определении члена класса целиком в заголовке? Если это правильно для шаблонов, почему бы и нет для обычных классов? У меня есть некоторые идеи для недостатков и преимуществ, но что у вас?
Каковы преимущества и недостатки реализации классов в файлах заголовков?
Ответ 1
Возможные преимущества поместить все в файлы заголовков:
- Меньшая избыточность (что приводит к более легким изменениям, упрощению рефакторинга и т.д.).
- Может предоставить компилятору/компоновщику лучшие возможности для оптимизации.
- Часто проще включать в существующий проект
Возможные недостатки помещения всего в файлы заголовков:
- Более длинные циклы компиляции/ссылок
- Потеря разделения интерфейса и реализации
- Может приводить к труднодоступным круговым зависимостям
- Множество инкрустаций может увеличить размер исполняемого файла
- Предотвращает двоичную совместимость разделяемых библиотек/библиотек DLL
- Расстраивает сотрудников, которые предпочитают традиционные способы использования С++
Ответ 2
Ну, одна проблема заключается в том, что типичные реализации меняются гораздо чаще, чем определения классов, поэтому для большого проекта вам приходится перекомпилировать мир для каждого небольшого изменения.
Ответ 3
Основная причина не в том, чтобы реализовать класс в файле заголовка: должны ли потребители вашего класса знать подробности его реализации? Ответ почти всегда нет. Они просто хотят знать, какой интерфейс они могут использовать для взаимодействия с классом. Наличие реализации класса, видимого в заголовке, значительно затрудняет понимание того, что это за интерфейс.
Помимо соображений компактности и разделения интерфейса от реализации, существуют также коммерческие мотивы. Если вы разрабатываете библиотеку для продажи, вы (возможно) не хотите передавать детали реализации библиотеки, которую вы продаете.
Ответ 4
Ты не повторяешься. Вы пишете код только один раз в одном заголовке. Он повторяется препроцессором, но это не ваша проблема, и это не нарушение DRY.
Если это правильно для шаблонов, почему бы и нет для обычных классов
Это не совсем то, что нужно делать для шаблонов. Это единственный, который действительно работает в целом.
В любом случае, если вы реализуете класс в заголовке, вы получаете следующие преимущества и недостатки:
- Полная реализация видна в любом месте, где она используется, что упрощает сборку при необходимости.
- Тот же код будет анализироваться и скомпилироваться несколько раз, что приведет к более высоким моментам компиляции.
- С другой стороны, если все в заголовках, это может привести к меньшему количеству единиц перевода, поэтому компилятор должен работать меньше раз. В конечном счете, вы можете получить единую единицу перевода, которая включает в себя только один раз, что может привести к очень быстрым компиляциям.
И... что это действительно.
Большая часть моего кода имеет тенденцию находиться в заголовках, но это потому, что большая часть моего кода - это шаблоны.
Ответ 5
Основным недостатком (помимо длинных сборок) является отсутствие четкого разделения интерфейса и реализации.
В идеале вам не нужно будет видеть реализацию интуитивно понятного и хорошо документированного интерфейса.
Ответ 6
Не упоминается: виртуальные функции создаются для каждого из них, поэтому вы можете раздувать ваш исполняемый файл (я не уверен, верно ли это для всех компиляторов).
Существует альтернатива:
Сделайте много вещей в классах, объявленных в вашем исходном файле. Например, pimpl-idiom, но есть также люди, которые боятся объявлять классы из заголовочного файла. Однако это имеет смысл для частных классов.