плохо конечно. потому что части программы становятся сильно связанными. это примерно также плохо как если б ты все вещи в доме перемешал, и разложил по полу кучками. так жить можно, но это неудобно.
не обязательно. такая функция может рассматриваться компилятором как инлайн функция. это полезно для особо высоких требований по скорости кода. но если же функция объемна(и компилятор ее инлайнить не будет), то это вредно во всех отношениях.
Во-первых, когда надо потрогать логику, компилять придётся не один только cpp-файл, а всё, что прямо или косвенно заинклудило h-файл. Если компиляция длительная, это может быть не удобно.
Во-вторых, лишняя писанина в h-файлах увеличивает время компиляции проекта в целом.
В-третьих, если надо инлайнить, то альтернатив особых нет.
В-четвертых, есть такая херовина - ODR. За её нарушение полагается UB. Смотри не оступись.
Раздельная компиляция появилась как вынужденная мера кода компьютеры были большие и медленные. Сейчас, когда компьютеры стали маленькие и быстрые, для маленьких проектов раздельная компиляция не является обязательной.
Раздельная компиляция появилась как вынужденная мера кода компьютеры были большие и медленные.
Что за ерунда. Раздельная компиляция помогает разрывать циклические зависимости. Без неё красивая архитектура софтины (сложнее хеллоу ворлда) превратится в кусок говна с бессмысленным выносом части логики и данных в базовые классы, часть этих сущностей вообще бы не была создана в случае раздельной компиляции.
Боюсь даже представить как приходится изгаляться всяким растоадептам, архитектура неминуемо страдает.
Только это, если пишешь логику в h, то неплохо выделить отдельный заголовчный файл под имплеменацию, а отдельный под объявление. Ну что бы не было говнопортянки на 100500 строк, когда нормально не посмотреть на декларацию
Воспользуюсь случаем, проведите ликбез для непосвященных - а можно вообще без всех этих .h писать? Как в питоне, в одном файле всё (про питонычьи модули понятно, это опциональное разбиение, не рассматриваем)?
раздельной компиляции 100 лет в обед. она была еще в первых ассемблерах, до появления всяких там си и тем более ооп.
Тут речь про конкретный язык, который выбрал для себя конкретную модель, и выбор это правильный, скорость компиляции не единственный фактор.
Если вы с товарищем выше согласны, то я не против, пишите свои поделки в hpp целиком, после килограма другого съеденного кактуса, вомзможно что-то начнет доходить даже до самых упорных. Невозможно комфортно что-то более менее сложное написать без раздельной компиляции
Сходу — eigen, autodiff, gmm++ — нефига не тривиальные header-only либы с кучей шаблонов.
Контейнеры STL — header-only либы. Вообще для шаблонов плюсовых это норма.
Раздельная компиляция помогает разрывать циклические зависимости.
Вообще никак не связанные вещи. Единственное что в этом плане дает раздельная компиляция - глобальные static переменные в разных единицах трансляции, но это такое себе…
Так то да, удобно когда можно значимую часть кода вынести в .cpp оставив лаконичный хидер. Но это не является обязательным/догматичным требованием и уж вообще никаким боком к циклическим зависимостям не относится. Если Вам для разрыва таких зависимостей требуется раздельная компиляция у Вас явно какая то беда с архитектурой. И в голове путаница.
class A {
void set_link(B *);
};
class B {
void set_link(A *);
};
Например, выкрутился, вынес реализацию за объявление классов, но вот появляется class С, который тоже имеет циклическую зависимость с A. Очевидно, что неудобно всё пихать в один файл (теперь ещё и C нужно добавить), и мы выносим реализации в отдельный hpp (a.hpp - a_impl.hpp, b.hpp - b_impl.hpp, …), и всё это в правильном порядке подключаем в отдельном hpp-агрегаторе. Можно вынести общую часть в отдельную сущность. Можно закостылить многопроходной компилятор.
Резюме - проблема циклических зависимосте существует и требует решение. Раздельная компиляция предлагает простой и элегантный способ - не ипешь себе мозг, делишь декларацию с реализацией и из релазации смотришь на любую декларацию
Очевидно, что неудобно всё пихать в один файл (теперь ещё и C нужно добавить), и мы выносим реализации в отдельный hpp (a.hpp - a_impl.hpp, b.hpp - b_impl.hpp, …), и всё это в правильном порядке подключаем в отдельном hpp-агрегаторе.
Обращаю внимание на то, что по сути пришли к тому же разделению заголовков и единиц трансляции, но только получили гемор с ручной дрочкой и замедлением компиляции. Раздельная же компиляция данных проблем не имеет.
В случае с шаблонами выхода нет, но в остальных случаях добровольный отказ от раздельной компиляции - идиотизм
А потом делаем эти классы шаблонами и переносим их опять в .hpp
В приведённом примере вообще достаточно задекларировать три класса сначала и фсе.
Итого - проблема циклических зависимостей существует, но раздельная компиляция к её решению никакого отношения не имеет. Исторически раздельная компиляция появилась именно как способ ускорения сборки, читайте воспоминания олдов:-)
Например, когда в разных compilation units один и тот же тип имеет разный размер, и они начинают передавать друг дружке указатель на экземпляр и работать с ним. Но стандарт говорит, что нарушение ODR само по себе является UB, afaik.
Я называю это «заметанием мусора под ковёр». С++ программисты гордятся что божественный ООП позволяет писать красивый и простой код. Вот только заглянешь в хидеры, а там ад и погибель беспорядочное нагромождение темплейтов на темплейте и всё это нечитаемое безобразие никак не прокомментировано.
Например, когда в разных compilation units один и тот же тип имеет разный размер, и они начинают передавать друг дружке указатель на экземпляр и работать с ним
Можешь пример накидать, не очень понимаю, что значит разный размер, для одного типа в разных единицах компиляции (трансляции?)? В рамках одной компиляции?