Запитати

Для чого потрібні Header файли в С++? Чому не можна писати без них?

Вирішено
30 жовтня 2020 · 285 ·
0

Що заважає підключати просто .cpp файли?

Ну підключив ти його два рази, ну нехай компілятор тільки один раз підключає і все, раз він все в один як би файл склеює, значить перше підключення буде вище за інших і буде видно внизу. Нехай дивиться час зміни і перекомпілюються тільки те що змінилося. Нехай автоматично генерує і прикріплює header файли з описом інтерфейсів до відкомпільованого бінарнику і т.п.

Іншими словами, чому рутинна робота по генерації хедер файлів, не автоматизована і покладена на розробника? Адже компілятор поруч з відкомпільованим бінарники може легко сам згенерувати файл опису інтерфейсів (який він отримав, скануючи cpp файл).

Можете навести ситуацію, в якій би виникали ПРОБЛЕМИ без використання хедер файлів? Це буде найкраще пояснення.

c c++ cpp header компіляція

Відповіді на питання (1)

30 жовтня 2020
0
Обране рішення

Проблема лежить в області забезпечення зворотної сумісності.

Подивіться, будь-яку новий мову програмування - наприклад Паскаль, не кажучи вже про Java або C # - не потребують заголовних файлах. Без сумніву, C++ теж міг би обійтися без них. У чому ж справа?

Перенесемося на півстоліття назад, в 1972 рік. Уявімо собі компілятор мови C.

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

У нас відразу ж виникає проблема: як скомпілювати функцію f, яка посилається на іншу функцію g? Нам потрібно окремий опис інших функцій. Ми могли б, звичайно, прочитати всі вихідні файли, для початку з'ясувати, які функції у нас є, і потім прочитати їх вдруге і скомпілювати один за одним. Але це було занадто складно і повільно, потрібно було парсити визначення функцій двічі, і один раз викидати результат! Це неприпустима витрата процесорного часу! Плюс, якщо тримати в пам'яті визначення всіх функцій, може знову-таки не вистачити пам'яті.

На кого Денніс вирішив покласти складну проблему відділення опису функції від її реалізації, і підключення тільки потрібних описів при компіляції даної функції? На нас, програмістів. Він вирішив, що ми повинні самі допомогти компілятору і скопіювати визначення функцій в окремий файл, і самі вказати компілятору, які файли з визначеннями потрібні. (Тобто перший крок компіляції покладається на нас.)

Це радикально спростило компілятор, але привело в свою чергу до проблем. Що буде, якщо ми забули підключити потрібні заголовки? Відповідь: помилка компіляції. Що буде, якщо зміст тексту заголовки змінюється в залежності від якого-небудь макросу? Відповідь: компілятор «тупий», і не намагається детектувати цю проблему, він перекладає відповідальність на нас.

На момент розробки мови це було правильне рішення. Компілятор виявився практичним, швидким, і програмісти були не проти допомогти компіляції. Ну і якщо хто припускався помилки, сам був винен.

Перемотати стрілки годинника в 1983 рік. Бьярн створює C++. Він вирішив злетіти на хвилі популярності мови C, і перейняв модель компіляції C з окремими translation unit'ами та пов'язаними з цим проблемами прямо з C. Втім, перші версії C++ були просто препроцесором мови C! Тому проблеми роздільної компіляції перекочували з C в C++. Більше того, додалися нові проблеми. Наприклад, шаблони класів виглядають як класи, але не генерують об'єктного коду самі по собі, тому для них доводиться йти на хитрощі і обходити недоліки системи роздільної компіляції (наприклад, включенням реалізації в header і трюками компоновщика).

А далі вступила в гру зворотна сумісність. Зараз, в 2017 році, ми маємо так багато коду, написаного в стилі «з заголовками», і так багато коду виходить з різних тонкощів, пов'язаних з цим, що міняти парадигму вже пізно, поїзд практично поїхав.

Втім, існує проект модульної системи в C++, який повинен допомогти програмістам позбутися спадщини півстолітньої давності. Він ще не реалізований, і в ньому є складнощі рівня дизайну (наприклад, в header'і був визначений макрос, чи буде його видно, якщо ми перейдемо від header'ів до модулів?) Сподіваюся, в майбутньому розробники мови таки зможуть побороти проблему зворотної сумісності.


Для відповіді на запитання необхідно авторизуватись

Вхід / Реєстрація