Страницы

Поиск по вопросам

среда, 18 декабря 2019 г.

Чем плохо писать C++ код в .hpp файлах

#cpp #библиотеки


Встречал и сам писал библиотеки одного .hpp файла. Удобно, что не нужно повторять
код. Чем это может быть плохо?
Вот пример довольно популярной и удачной библиотеки.
    


Ответы

Ответ 1



Плохо в этом то, что вы теряете преимущества раздельной компиляции. Во-первых, это время. Ваша функция будет компилироваться каждый раз, когда cpp-файл включает этот header. Хуже того, теперь при каждом изменении подробностей реализации придётся перекомпилировать не один cpp-файл с имплементацией, а все, которые включают ваш header. Во-вторых, это увеличивающееся количество зависимостей. Если вам для декларации функции не нужны другие header'ы, а для имплементации нужны, то теперь вы вынуждены включать всё в header, и значит, все, кто его используют ваш header, тоже будут «видеть» эти другие header'ы. К этому непосредственно примыкает и проблема номер 3: кольцевые зависимости. Допустим, у вас есть две функции в разных файлах, которые вызывают друг друга. Если в header'ах только декларации функций, то cpp-файлах можно подключить недостающий header, и функции могут легко ссылаться друг на друга. В случае, когда имплементация в header'е, такое не пройдёт из-за взаимной рекурсии включений, и вам придётся идти на уродливые трюки наподобие «точно знать, какие функции нужны другому header'у, и предварительно объявить их перед включением». И наконец, вы теряете инкапсуляцию: любой может видеть вашу имплементацию, и это провоцирует кодировать используя знание о том, как же там всё реально устроено (что по очевидным причинам плохо). Заметьте, что если ваша функция — шаблонная, то вам скорее всего таки придётся объявлять её полностью в header'е, и столкнуться со всеми вышеперечисленными проблемами.

Ответ 2



Реализация в заголовочных файлах не просто возможна, но и требуется в нескольких случаях. В частности, при реализации обобщённых типов, они же шаблоны (templates), а также при реализации встроенных (inline) функций. С другой стороны, в некоторых случаях такая реализация может привести к ошибкам во время линковки, поскольку одна и та же функция окажется в разных .obj-файлах. Чтобы этого не произошло, функцию необходимо объявить статической (static), тогда она не будет видна из других объектных модулей. Фактически, это означает, что в каждом объектом модуле будет своя копия этой функции. Хочу обратить внимание, что в данном случае речь идёт не о статических методах класса, которые также принято обозначать ключевым словом static. Резюме: это не плохо, и иногда необходимо. Главное, понимать, что и зачем вы делаете.

Ответ 3



Принципиально ничего плохого в этом нет. Вон boost больше чем на половину в заголовках реализован. Минусы это увеличение времени компиляции и размера бинаря (не обязательно).

Комментариев нет:

Отправить комментарий