Существует несколько проблем с моделью #include, используемой в C / C ++, главная из которых заключается в том, что она не выражает фактический граф зависимостей. Вместо этого он просто объединяет группу определений в определенном порядке, часто приводя к тому, что определения приходят в другом порядке в каждом исходном файле.
Как правило, иерархия включаемых файлов вашего программного обеспечения - это то, что вам нужно знать точно так же, как вы знаете свои структуры данных; Вы должны знать, какие файлы включены откуда. Прочитайте ваш исходный код, узнайте, какие файлы находятся выше в иерархии, чтобы избежать случайного добавления включения, чтобы оно было включено «отовсюду». Подумайте, когда вы добавите новое включение: мне действительно нужно включить это здесь? Какие другие файлы будут нарисованы, когда я сделаю это?
Два соглашения (помимо уже упомянутых), которые могут помочь:
- Один класс == один исходный файл + один заголовочный файл с постоянным именем. Класс A идет в A.cpp и A.h. Шаблоны кода и фрагменты кода хороши здесь, чтобы уменьшить объем ввода, необходимый для объявления каждого класса в отдельном файле.
- Используйте Impl-шаблон, чтобы не отображать внутренние элементы в заголовочном файле. Шаблон impl означает помещение всех внутренних членов в структуру, определенную в файле .cpp, и просто наличие частного указателя с предварительным объявлением в классе. Это означает, что файл заголовка должен включать только те файлы заголовка, которые необходимы для его открытого интерфейса, а любые определения, необходимые для его внутренних членов, будут храниться в файле заголовка.