Функции в заголовках C / C ++ не нужны? - PullRequest
2 голосов
/ 15 апреля 2011

Я работаю над очень маленьким кусочком исходного кода C / C ++. Программа считывает входные значения из стандартного ввода, обрабатывает их алгоритмом и записывает результаты в стандартный вывод.

Я бы просто реализовал все это в одном файле, но мне также нужны тестовые случаи для алгоритма (не чтение ввода / вывода), поэтому у меня в проекте есть следующие файлы:

  • main.cpp
  • sort.hpp
  • sort_test.cpp

Я реализую алгоритм сразу в sort.hpp, без sort.cpp. Он довольно короткий и не имеет никаких зависимостей.

Не могли бы вы сказать, что в некоторых случаях функции, определенные в заголовках, подходят, даже если они представляют собой сложные алгоритмы, а не просто методы доступа / мутаторы? Или есть причина, по которой я должен избегать этого? Когда я должен переместить код из заголовка в исходный файл?

Ответы [ 8 ]

8 голосов
/ 15 апреля 2011

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

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

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

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

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

Многие популярные библиотеки используют стратегию только с заголовками.

1 голос
/ 15 апреля 2011

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

1 голос
/ 15 апреля 2011

Можно добавить любую функцию в заголовок, если она inline.Такие вещи, как функции, определенные внутри class { }, и шаблоны неявно inline.

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

* 1008.* Конечно, если вы хотите распространять код как библиотеку, то выбор между заголовком, статической библиотекой или двоичным файлом динамической библиотеки является важным решением, влияющим на пользователей.
0 голосов
/ 15 апреля 2011

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

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

0 голосов
/ 15 апреля 2011

Если вы хотите встроить функцию, она ДОЛЖНА быть в заголовке, иначе она не может быть встроена.

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

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

0 голосов
/ 15 апреля 2011

Подавляющее большинство библиотек boost предназначены только для заголовков, поэтому я бы сказал: да, это установившаяся и принятая практика.Только не забудьте inline.

0 голосов
/ 15 апреля 2011

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

0 голосов
/ 15 апреля 2011

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

inline int max(int a, int b)
{
  return (a > b) ? a : b;
}

http://en.wikipedia.org/wiki/Inline_function

...