Должен ли я включить файлы, включенные в другой заголовок? - PullRequest
2 голосов
/ 11 декабря 2010

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

Например, скажем, класс C наследуется от класса B, который содержит класс A. Теперь, конечно, поскольку класс B содержит класс A в качестве члена, он должен включать a.h в b.h.Однако, скажем, C также должен включать a.h.Будучи ленивым, я просто включаю b.h (который C должен включать в любом случае), и, поскольку b.h уже включает a.h, мне не нужно ничего больше включать, и он прекрасно компилируется.То же самое для моих файлов .cpp: я просто включаю заголовок, и все, что включено в заголовок, будет автоматически включено в мой файл .cpp, поэтому я не включаю его туда.

Это плохая привычкамой?Это делает мой код менее читабельным?

Ответы [ 3 ]

6 голосов
/ 11 декабря 2010

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

4 голосов
/ 11 декабря 2010

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

В вашем случае, если c.h объявляет class C который наследуется от class B, очевидно, вы должны включить B.h.Однако, если class A никогда не появится в c.h, я полагаю, что нет причин для его включения.Тот факт, что b.h упоминает A, означает, что b.h должен сделать то, что необходимо для анализа, либо путем объявления вперед A, либо с учетом a.h.

Так что, с моей точки зрения, вывы делаете то, что должно быть сделано.

Также обратите внимание, что если по некоторым причинам c.h начнет упоминать A, я бы добавил соответствующее объявление include или forward, чтобы не зависеть от того факта, что b.h делает это для меня.

2 голосов
/ 11 декабря 2010

Лучше всего включать каждый заголовок с определениями, которые вы используете напрямую.

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

EDIT:

Краткий пример:

  • Класс B использует класс A, например, реализация B хеш-таблицы, использующая механизм хеширования A

  • Вы создаете класс C, которому нужна хеш-таблица (то есть B) и алгоритм хеширования (то есть A) для какой-то другой цели. Вы включаете B.h и пропускаете A.h, поскольку B.h в любом случае включает его.

  • Мэри, одна из ваших коллег, обнаружила статью об этом новом невероятном алгоритме хеширования, который уменьшает вероятность столкновений, в то время как ему требуется на 10% меньше места и он в два раза быстрее. Она (правильно) переписывает класс B, чтобы использовать класс D, который реализует этот алгоритм. Поскольку класс A больше не нужен в B, она также удаляет все ссылки на него из B.h.

  • Ваш код ломается.

РЕДАКТИРОВАТЬ 2:

Есть некоторые программисты (и я иногда в этом тоже виноват, когда тороплюсь), которые занимаются этой проблемой, имея в своем проекте заголовочный файл «include-all». Этого следует избегать, поскольку это приводит к загрязнению пространства имен беспрецедентных масштабов. И да, windows.h в MSVC, по моему мнению, является одним из таких случаев.

...