Ключа практик здесь имея вокруг каждого foo.h файл охранника, такие как:
#ifndef _FOO_H
#define _FOO_H
...rest of the .h file...
#endif
Это предотвращает множественное-включение, с петли и все такие сопутствующие ужасы. После того, как вы гарантируете, что каждый включенный файл, таким образом, охраняется, специфика менее важна.
Мне нравится один руководящий принцип. Адам выражает: убедитесь, что если исходный файл содержит только a.h
, он не обязательно будет получать ошибки из-за a.h
, предполагая, что перед ним были включены другие файлы - например. если a.h
требует, чтобы b.h
был включен раньше, он может и должен включать только b.h (охранники сделают это noop, если b.ч был уже включены ранее)
И наоборот, исходный файл должен включать в себя заголовки, из которых он требует, что-то (макросы, декларации и т.д.), не предполагают, что другие заголовки просто приходят в волшебно, потому что у него есть включено какой-нибудь.
Если вы используете классы по стоимости, увы, вам нужны все детали gory класса в некотором .h
, который вы включили. Но для некоторых применений с помощью ссылок или указателей достаточно простого class sic;
. Например, при прочих равных условиях, если класс a может уйти с указателем экземпляру класса b (т. Е. Члену class b *my_bp;
, а не члену class b *my_b;
), связь между включенными файлами может быть уменьшена (уменьшая значительную перекомпиляцию) - например b.h
может иметь немного больше чем class b;
в то время как все окровавленные детали в b_impl.h
который входит только заголовки, которые действительно нужно ...
@mgd - Если у меня есть заголовок, содержащий 10 включений, и у источника было 10 различных включений, нужно ли просто переместить включения из заголовка в исходный код, чтобы источник содержал 20? –
См. Более полный ответ alex. Единственное исключение - если у вас есть предварительно скомпилированные заголовки, в этом случае включают все заголовки платформы/рамки/ОС, которые никогда не будут меняться в один файл и включают в себя всюду –