Практические правила размещения функций в заголовочных файлах
В последнее время я начал добавлять все больше функций в заголовочные файлы, в основном для удобства. Но я боюсь, что могу перестараться, мои заголовки полны включений, и я не уверен, что это хорошая идея.
Каковы ваши практические правила для перемещения функций из или в заголовочные файлы?
Если вам интересно, я говорю о разработке приложений, а не библиотек.
Редактировать:
Полагаю, это полезно, если я нарисую плюсы / минусы встроенных (естественно) функций заголовка по сравнению с функциями реализации с моей точки зрения:
Про встроенный:
- Более чистый / лаконичный.
- Нет необходимости дублирования подписи.
- Нет необходимости изменять какой-либо Makefile для связи с новыми файлами.
- Мгновенная возможность ввести параметры шаблона.
Contra inline:
- Увеличенное время компиляции (мне все равно)
- Многие включают в заголовки (не должно быть такой большой проблемой, если они используют охрану)
В соответствии с этим кажется хорошей идеей помещать практически все функции в заголовки, и я считаю, что это довольно близко к тому, что делают STL и Boost (хотя это и библиотеки, в отличие от моего кода).
7 ответов
Одно из моих самых нерушимых правил: в заголовочных файлах допускаются только встроенные тела функций. Все остальное вызывает проблемы с несколькими определениями в фазе связи.
Заголовки следует оставлять преимущественно для деклараций, а не для определений. У меня есть исключения из этого правила (будучи гибким типом), но ни одно из них не связано с не встроенными функциональными органами.
Мое эмпирическое правило: "Не в заголовке, если нет необходимости". А что касается удобства, считаете ли вы удобным увеличение времени компиляции?
Есть несколько очевидных технических аспектов - шаблоны и встроенные функции должны быть в заголовках - заголовки, включенные из нескольких блоков перевода, должны быть осторожны с правилом единого определения - более прямо, вы бы хотели кровавую вескую причину даже подумать о внесении реализации функции в заголовке, и я не могу вспомнить ни разу, когда меня даже соблазнили.
Итак, вопрос сводится к:
встроенный в заголовке и вне строки в файле реализации?
Факторы:
- вы говорите, что разрабатываете код уровня приложения, а не библиотеки, поэтому вам не нужно (в настоящее время) беспокоиться о зависимости других команд от вашего кода и не сводить к минимуму необходимость их перекомпиляции (а не просто перекомпоновки), не допуская реализации
- НО, если вы пишете хороший код, который потенциально может стать полезным для других команд, вы можете захотеть сохранить конфиденциальность реализации
- встроенный или внеплановый тип обычно представляет собой издержки порядка для тривиальных функций получения / установки данных... если у вас есть функции, которые вызываются повторно из кода, критичного к производительности, то у вас есть причина предпочесть встраивание
- Реализация в заголовке (особенно если она смешана с объявлениями) часто может запутывать API, но иногда фактически делает код более самодокументированным
- локализация и устранение избыточности (объединение декларации / определений) определенно устраняет возможность опечаток / ошибок и часто может повысить производительность
Итог: если вы обнаруживаете, что делаете это все больше и больше, тогда это, очевидно, работает на вас, и нет особой причины думать, что вас вот-вот обожгут. Следите за потенциальными проблемами, но не переусердствуйте, черт возьми, из материала, основанного на некоторой гипотетической и маловероятной проблеме.
Я использую два правила:
1) Если это встроенные функции
2) Если это шаблонная функция.
Во-первых, функция шаблона должна быть помещена в заголовки.
Кроме того, функции с пустым телом, такие как конструктор по умолчанию или по умолчанию, но виртуальный деструктор, могут быть помещены в заголовки.
Я никогда не пользуюсь inline
потому что компилятор не гарантирует этого.
Хороший стандарт кодирования скажет вам реализовать методы и функции в исходном (cpp) файле.
Если вы предпочитаете это, вы можете реализовать шаблоны и встроенные функции в заголовке.
Так как это было помечено как C++
почему бы вам не разделить их на логические class
эс?
Обычно у меня есть один class
объявление в заголовочном файле и его определение в соответствующем исходном файле.