Ключевой практикой здесь является наличие вокруг каждого файла 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.h был уже включен ранее)
И наоборот, исходный файл должен включать заголовки, из которых он что-то требует (макросы, объявления и т. д.), не предполагать, что другие заголовки появляются волшебным образом, потому что некоторые из них были включены.
Если вы используете классы по значению, увы, вам нужны все детали класса в некоторых .h
, которые вы включаете. Но для некоторых применений через ссылки или указатели будет достаточно простого class sic;
. Например, при прочих равных условиях, если классу a удается использовать указатель на экземпляр класса b (то есть элемент class b *my_bp;
, а не элемент class b *my_b;
), связь между включаемыми файлами может быть установлена. слабее (уменьшая количество перекомпиляции) - например. В b.h
может быть немного больше, чем class b;
, в то время как все кровавые подробности находятся в b_impl.h
, который включается только в заголовки, которые действительно в нем нуждаются...
person
Alex Martelli
schedule
09.11.2009