Наиболее известными являются OCaml и F # (которые можно смутно описать как OCaml для .NET).
Есть много других мультипарадигмальных языков, таких как Оз , но они имеют в основном педагогическую ценность. В отличие от OCaml очень практично. Это почти так же быстро, как C и почти так же красиво, как Haskell:)
Популярные языки сценариев, такие как Python и Ruby, позволяют программировать и в функциональном стиле. Однако они не предоставляют одно из самых мощных средств, которые есть у «классических» функциональных языков (а также OCaml): сопоставление с образцом (не путайте его с регулярным выражением).
Вариант 1 позволяет хранить все определения в одном месте, так что вам нужно включать / искать только один файл вместо того, чтобы включать / искать много файлов. Это преимущество более очевидно, если ваша система поставляется как библиотека третьей стороне - они не очень заботятся о структуре вашей библиотеки, они просто хотят иметь возможность ее использовать.
Я думаю, что главная мотивация №1 - это ... лень. Люди думают, что либо слишком сложно управлять зависимостями, которые разделение вещей на отдельные файлы может сделать более очевидным, и / или думают, что иметь отдельные файлы для всего - это как-то «излишне».
Это также, конечно, часто может быть случай по «историческим причинам», когда программа или проект выросли из чего-то небольшого, и никто не нашел времени на рефакторинг файлов заголовков.
Еще одна причина для использования разные .h для каждого .c - время компиляции. Если существует только один .h (или если их больше, но вы включаете их все в каждый .c-файл), каждый раз, когда вы вносите изменения в .h-файл, вам придется перекомпилировать каждый .c-файл. В большом проекте это может означать потерю драгоценного времени, что также может нарушить ваш рабочий процесс.
Три правила для выполнения # 2 и никаких проблем:
запускать КАЖДЫЙ заголовочный файл с
#ifndef _HEADER_Namefile
#define _HEADER_Namefile_
завершите файл с помощью
#endif
, что позволит вам включать один и тот же файл заголовка несколько раз в один и тот же модуль (это может произойти непреднамеренно) без каких-либо проблем.
у вас не может быть определений в ваших файлах заголовков. .. и это то, что каждый думает, что он / она знает о прототипах функций, но почти всегда игнорирует глобальные переменные. Если вам нужна глобальная переменная, которая по определению должна быть видна вне ее определяющего модуль C, используйте ключевое слово extern:
extern unsigned long G_BEER_COUNTER;
, который указывает компилятору, что символ G_BEER_COUNTER на самом деле является беззнаковым длинным (так что работает как объявление), что в каком-то другом модуле будет правильное определение / инициализация. (Это также позволяет компоновщику сохранять разрешенную / неразрешенную таблицу символов.) Фактическое определение (тот же оператор без extern) находится в файле .c модуля.
Я также считаю, что существует третий вариант: каждый .c
имеет свой собственный .h
, но есть еще один .h
, который включает все остальные файлы .h
. Это объединяет лучшее из обоих миров за счет обновления .h
, хотя это может быть сделано автоматически.
С помощью этой опции вы внутри себя используете индивидуальный .h
], но сторонняя сторона может просто включить всеобъемлющий файл .h
.
В C ++ вам определенно понадобится один файл заголовка для каждого класса и использование предварительно скомпилированных заголовков, как упомянуто выше.
Один файл заголовка для всего проекта не работает, если проект не очень маленький - как школьное задание
Когда у вас есть очень большой проект с сотнями / тысячами небольших файлов заголовков, проверка зависимостей и компиляция могут значительно замедлиться, поскольку необходимо открывать и читать множество небольших файлов. Эту проблему часто можно решить, используя предварительно скомпилированные заголовки.
Это зависит от того, сколько функций содержится в одном заголовочном / исходном файле. Если вам нужно включить 10 файлов, например, чтобы что-то отсортировать, это плохо.
Например, если я хочу использовать векторы STL, я просто включаю их, и меня не волнует, какие внутренние компоненты необходимы для использования вектора. GCC включает 8 других заголовков - распределитель, базу алгоритмов, конструкцию, неинициализированный, вектор и bvector. Было бы больно включать все эти 8 только для использования вектора, согласитесь?
НО внутренние заголовки библиотеки должны быть как можно более разреженными. Компиляторы более довольны, если они не включают ненужный материал.