Зачем мне компилировать 2 исходных файла C / ++ вместо использования файла заголовка?

Я недавно начал изучать make-файлы, и видео, которое я смотрю, включает в себя компиляцию двух исходных файлов и файла заголовка. Класс был определен в файле заголовка, который был включен в оба исходных файла. Метод для класса был определен в одном исходном файле и вызван во втором (main.cpp). Зачем мне нужно иметь 2 исходных файла (.c / .cpp)?


person Serket    schedule 03.07.2020    source источник
comment
вы понимаете, почему вы должны разделять код на заголовок и исходный код? Как только вы это сделаете, вы также узнаете, почему не хотите помещать все в заголовок.   -  person 463035818_is_not_a_number    schedule 04.07.2020
comment
@ idclev463035818 вы можете объяснить, почему я должен разделять заголовок и источник? Насколько я понимаю, это для организационных целей.   -  person Serket    schedule 04.07.2020
comment
Заголовок копируется в исходный файл во время предварительной обработки. В результате в компилятор загружается гигантский файл. Если все находится в заголовках, то каждый раз, когда вы вносите изменения, будет создан один файл. Он будет включать в себя заголовки проекта, и это одно изменение приведет к перекомпиляции ВСЕХ файлов. На это уходит очень много времени.   -  person user4581301    schedule 04.07.2020
comment
https://stackoverflow.com/questions/1305947/why-does-c-need-a-separate-header-file/1306069   -  person 463035818_is_not_a_number    schedule 04.07.2020
comment
@ user4581301 тогда что произойдет, если у меня есть несколько исходных файлов, но два из них имеют основные функции. Кроме того, не могли бы вы опубликовать все это в качестве ответа? Спасибо   -  person Serket    schedule 04.07.2020
comment
Заголовки содержат интерфейс. Интерфейс особо не изменился. В большинстве случаев меняются детали в файлах реализации. С заголовками и файлами реализации вам нужно только перекомпилировать файлы реализации, которые изменились, а иногда и целую кучу вещей при изменении интерфейса.   -  person user4581301    schedule 04.07.2020
comment
Прочтите Как работает процесс компиляции / связывания?. Когда вы закончите, все остальное обретет смысл. Если у вас есть идентификатор, который существует более одного раза, компоновщик не узнает, какой из них следует использовать. Если у вас есть два файла с main, оба файла будут компилироваться, но компоновщик не может выбрать, какой из них использовать.   -  person user4581301    schedule 04.07.2020
comment
Помещение реальных методов и реализаций функций в файлы заголовков создает возможность существования нескольких экземпляров одного и того же метода или функции, когда объектные файлы связаны вместе. Это может значительно увеличить время компиляции для больших базовых показателей кода, поскольку одни и те же функции или методы придется компилировать много раз. Также, вероятно, существуют всевозможные тонкие проблемы, возникающие из-за наличия нескольких экземпляров функции или метода, если такая схема будет использоваться.   -  person Andrew Henle    schedule 04.07.2020


Ответы (2)


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

В ПОРЯДКЕ. Итак, один main.cpp, который включает в себя десятки, сотни или тысячи файлов в программе, все они реализованы в файлах заголовков разумного размера, каждый из которых охватывает одну концепцию или объединяет несколько файлов заголовков, если одна концепция слишком широка, чтобы ее можно было легко описать < sup> 1 в одном заголовке. Проблема решена, да? Ага. Но это только одна проблема.

А как насчет потребления ресурсов?

Перед этим полезно ознакомиться с Как работает процесс компиляции / связывания? продолжая.

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

Память продолжает дешеветь, поэтому ограничение первого ресурса не так важно, как это было в 1970-х годах, когда все это изобреталось 2. По-прежнему время от времени поднимает свою уродливую голову. Вот почему я компилирую кросс-компиляцию на большом и толстом ПК, а не пишу код непосредственно на Raspberry Pi.

Время не дешевеет. Никогда не было и не будет.

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

В редких случаях, когда интерфейс меняется, ну, вы терпите.

1 Потому что это и есть код: описание поведения. Это не список инструкций для выполнения компьютером - это вывод компилятора - это описание поведения программы. Задача компилятора - превратить ваше описание в инструкции.

2 Это также объясняет, почему создание на недавно созданных языках намного проще 3. У них не осталось лишнего багажа, чтобы заставить все работать в славные дни 1/2 КБ оперативной памяти и процессоры с тактовой частотой в килогерцах. Они также извлекли уроки из множества ошибок.

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

person user4581301    schedule 03.07.2020

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

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

Вы также захотите разделить исходный код на отдельные файлы для удобства навигации. Работа с исходным файлом из 2000+ строк намного сложнее, чем с 10 файлами по 200 строк каждый. Это даже более важно, когда срабатывает контроль версий, и вы работаете в команде, поскольку тогда конфликты слияния уменьшаются.

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

На практике у вас часто будет один класс на исходный файл с соответствующим файлом заголовка. Функции логически сгруппированы в наборы, каждый в своей паре заголовочный / исходный файлы.

person tadman    schedule 03.07.2020